Comment remplacer plusieurs lignes par un seul mot dans le fichier (remplacement sur place)?

9

Le contenu de mon filenamefichier est le suivant (par exemple):

My block of line starts from here 
START
First line
second line
third line
END
and end to here for example.

Je veux remplacer un bloc de lignes entre STARTet ENDpar un seul mot, par exemple avec SINGLEWORD. Comme ci-dessous:

My block of line starts from here 
SINGLEWORD
and end to here for example.

Je peux trouver mon bloc de lignes en utilisant cette commande:

grep -Pzo "START(.|\n)*END" filename

Et le résultat de l'exécution de la commande ci-dessus sera comme ceci:

START
First line
second line
third line
END

Ensuite, j'ai utilisé cette commande pour combiner toutes les lignes en une seule ligne:

LAST_RESULT | sed -e :a -e '/$/N; s/\n/ /; ta'

Ensuite, j'obtiendrai ce résultat:

START First line second line third line END

Et avec ma dernière commande, LAST_RESULTS | sed 's/.*/SINGLEWORD/'je les change en "SINGLEWORD"et j'obtiens ce résultat.

SINGLEWORD

Maintenant, ce que je veux, c'est: Comment puis-je utiliser cette commande (ou votre commande de suggestion) et remplacer (en place) mon bloc de lignes par le mot "SINGLEWORD"? Et le résultat final sera comme ce fichier:

My block of line starts from here 
SINGLEWORD
and end to here for example.
αғsнιη
la source

Réponses:

14

Cela peut être fait très facilement dans perl:

$ perl -i -p0e 's/START.*?END/SINGLEWORD/s' file
$ cat file
My block of line starts from here 
SINGLEWORD
and end to here for example. 

Explication

-0 définit le séparateur de lignes sur null

-pappliquer le script donné par -eà chaque ligne et imprimer cette ligne

Le modificateur regexp:

  • /sTraitez la chaîne comme une seule ligne. C'est-à-dire, changez .pour correspondre à n'importe quel caractère, même une nouvelle ligne, qui normalement ne correspondrait pas.

Pourquoi ?:

  • Par défaut, un sous-motif quantifié est "gourmand", c'est-à-dire qu'il correspondra autant de fois que possible (étant donné un emplacement de départ particulier) tout en permettant au reste du motif de correspondre. Si vous voulez qu'il corresponde au nombre minimum de fois possible, suivez le quantificateur avec a ?.
Sylvain Pineau
la source
@KasiyA: L'utilisation seddevrait être possible mais probablement plus difficile à lire (regardez cette question )
Sylvain Pineau
Un plus parce que mon modèle et END a DÉMARRAGE les caractères spéciaux ( /, *, ?) dans et ce ne sont que par exemple. et pourriez-vous expliquer votre commande.
αғsнιη
@KasiyA vous pouvez échapper à ces personnages avec \ (exactement comme avec sed): \/, \*,\?
Sylvain Pineau
@KasiyA j'ai essayé perl -i -p0e 's/\/\*.*?\*\//SINGLEWORD/sm'. Ça devrait marcher
Sylvain Pineau
@KasiyA Je pense que j'en ai fini avec les explications maintenant;)
Sylvain Pineau
14

Je me demandais si c'est possible sans perl, pythonet d'autres. Et j'ai trouvé cette solution en utilisant sed:

$ sed ':a;N;$!ba;s/START.*END/SINGLEWORD/g' filename

Explication:

  1. : a créer une étiquette 'a'
  2. N ajoute la ligne suivante à l'espace de motif
  3. $! si ce n'est pas la dernière ligne , ba branche (allez à) étiquette 'a'
  4. s remplacer , /START.*END/par SINGLEWORD, / g correspondance globale (autant de fois que possible)

Il a été trouvé ici .

@KasiyA, merci d'avoir appris beaucoup de choses intéressantes!

c0rp
la source