Sed: Remplacer le motif à chaque deuxième ligne?

10

Existe-t-il un moyen de dire sedde remplacer le modèle à chaque seconde occurrence? Ou au moins sur une ligne sur deux? (Bien sûr, c'est possible avec un script, mais je me demandais si je pouvais le sedfaire).

Éditer

j'ai trouvé

sed -e "s/pattern/replacement/g;n"

Mais il a remplacé chaque première occurrence, pas la seconde.

Exemple

Fichier d'entrée:

I have a pattern in each line
Also the second line has the pattern
Another pattern here
And -- you guess it -- a pattern

Sortie désirée:

I have a pattern in each line
Also the second line has the replacement
Another pattern here
And -- you guess it -- a replacement
Matthieu Riegler
la source

Réponses:

6

voir /programming/5858200/sed-replace-every-nth-occurrence

La solution utilise awk plutôt que sed, mais "utilisez le bon outil pour le travail". Il peut être possible ou non de le faire dans sed mais, même si c'est le cas, ce sera beaucoup plus facile dans un outil comme awk ou perl.

cas
la source
1
En utilisant ce que j'ai appris là-bas, j'ai pu sed -e 'n;s/2004-2009/6e législature/g'résoudre mon problème.
Matthieu Riegler
1
qui n'obtiendra pas chaque seconde occurrence , il recherchera votre modèle sur chaque seconde ligne . c'est à dire sauter les 1ère, 3ème, 5ème, 7ème, etc lignes. bien sûr, cela pourrait toujours fonctionner pour votre document particulier.
cas
Ouais je sais. c'est ce dont j'avais besoin en fait.
Matthieu Riegler
14
sed 's/pattern/replacement/2'

Remplacera la deuxième occurrence sur chaque ligne qui a le motif.


si vous avez GNU sed:

sed '1~2N ; s/pattern/replacement/2'

À partir de la première ligne 1, la ligne qui suit sera ajoutée à l'espace de motif, Npuis la scommande remplacera la deuxième occurrence du motif. puis seddéplacera deux lignes vers le bas ~2et répétera.

llua
la source
Je ne veux pas de la seconde mais de chaque seconde.
Matthieu Riegler
J'ai un motif par ligne. Ça ne marchera pas.
Matthieu Riegler
ça aurait été bien de le savoir avant. Donc, le motif se produit sur la ligne un, deux, trois et quatre (etc.), et vous souhaitez remplacer le motif sur la ligne deux, quatre, etc.?
llua
une alternative plus courte peut être code(sed '1 ~ 2s / motif / remplacement /')
jaap
2

L'interprétation simple:

Sur la première ligne qui contient au moins une occurrence de PATTERN, vous souhaitez l'ignorer et imprimer la ligne telle quelle. Sur la deuxième ligne qui contient au moins une occurrence de PATTERN, vous souhaitez remplacer la première instance de PATTERN par REPLACEMENT. Sur la troisième ligne qui contient au moins une occurrence de MOTIF, vous souhaitez imprimer la ligne telle quelle. Sur la quatrième ligne qui contient au moins une occurrence de PATTERN, vous souhaitez remplacer la première instance de PATTERN par REPLACEMENT. Etc. Les lignes qui ne correspondent pas au MOTIF doivent être imprimées sans modification.

Cela peut être facilement fait avec Sed comme ceci:

sed -e '/PATTERN/ { :inside' -e 'n;s//REPLACEMENT/;t' -e 'b inside' -e '}'

Ou, avec moins d'espaces et une étiquette plus courte:

sed -e '/PATTERN/{:i' -e 'n;s//REPLACEMENT/;t' -e 'b i' -e '}'

EDIT: Je viens de relire la question et repéré l'interprétation plus difficile:

Remplacez la deuxième occurrence de MOTIF dans tout le document par REMPLACEMENT, qu'elle se produise sur la même ligne que la première occurrence ou non. Laissez les première et troisième occurrences inchangées. Etc.

Je pense que cela peut aussi être fait avec Sed, bien que ce soit BEAUCOUP plus compliqué et je crois que cela dépend de l'expression régulière à utiliser. Je vais essayer de travailler sur quelque chose et de le poster, mais je vais laisser cette réponse avec la version simple ci-dessus pour l'instant.

Caractère générique
la source
remplacez votre test par un quit et prenez une entrée comme, { sed '...'; cat; } <inputpour un seul remplacement
mikeserv
1

Vous étiez très proche, sautez simplement la première ligne:

sed '1n;s/pattern/replacement/;n'

Pourquoi devrait awkêtre le meilleur outil dans ce cas?

Philippos
la source
0

Un modèle de symbole sur une seule ligne: sed 's / (a ​​[^ a] *) a / \ 1c / g'

Chaque deuxième motif (une seule correspondance de motif par ligne peut apparaître. Si deux correspondances ou plus par ligne apparaissent, seul le second sera remplacé)

echo -e "test\nreplace_me\ntest\ntest\nreplace_me\nreplace_me\nreplace_me" | \
sed '/replace_me/{:a;N;/replace_me.*replace_me/!Ta;s/replace_me/replaced/2;}'
se ruer
la source