Comment puis-je utiliser sed ou ex pour remplacer un bloc (code multiligne) par un nouveau bloc de texte (code)?


9

Je dois remplacer un gros bloc de texte (code de script shell) dans un fichier par un autre bloc de texte.

Je suis impressionné par le Comment puis-je utiliser sed pour remplacer une chaîne multi-lignes? répondu par antak et Multi-line replace répondu par Bruce Ediger

Mais j'ai du mal à les utiliser.

  1. antak a déjà mentionné dans sa réponse que le streaming de fichier entier ( 1h;2,$H;$!d;g;) vers le tampon n'est pas recommandé pour les fichiers volumineux, car cela surchargerait la mémoire.

  2. Je sais sedpeut être utilisé avec la fonction de bloc pour conserver le texte en dehors du bloc inchangé. Je souhaite utiliser cette fonctionnalité. Mais si j'utilise,

    sed -i '/marker1/,/marker2/s/.*/new text (code)/' filename
    

il insérera un nouveau texte (code) à plusieurs reprises pour chaque flux. Par conséquent, je dois faire le bloc visuel en un seul flux, en utilisant quelque chose de similaire à ce qui a été suggéré par antak plus tôt, mais pour le bloc (pas pour le fichier entier).

  1. Comme mentionné par Bruce Ediger, la fonctionnalité d'ajout exqui commence par se atermine par .(point) peut être essayée, mais mon nouveau texte (code) contient des lignes commençant par un point, qui peut être considéré comme le point de la syntaxe de l'ajout. Comment puis-je l'utiliser dans cette situation?

  2. ex's dd' nombre de lignes 'peut supprimer plusieurs lignes, mais si j'ai un bloc entre / marker1 / et / marker2 / avec le nombre de lignes non fixe (variable) doit être remplacé par un nouveau texte (code), comment faire il ?


Je trouve votre utilisation du terme «bloc visuel» inhabituelle et déroutante. Vous voulez dire simplement un bloc (groupe) de lignes complètes consécutives?
Scott

Oui, je modifie la question pour éviter toute confusion.
gibies

Quelle est la source du texte de remplacement? Est-ce dans un fichier ou est-ce "uniquement dans l'esprit des programmeurs"?
don_crissti

Il s'agit de la correction situationnelle d'un script shell. Par conséquent, la source du texte de remplacement est l'esprit du programmeur (ou un script maître sur lequel sedou une excommande fonctionne).
gibies

Don Crissti J'aurais utilisé rla commande read file, pour copier le texte d'un autre fichier, si la source du texte de remplacement se trouve dans un fichier.
gibies

Réponses:


10

Je suggère d'utiliser la commande c hange (qui est essentiellement un d elete couplé à un a ppend, bien que l'append ne soit appliqué que pour la dernière ligne de la plage qui est exactement ce que vous voulez ici):

sed -i '/marker1/,/marker2/c\
New text 1\
New text 2' filename

Ici, en utilisant sedla syntaxe de GNU pour l'édition sur place ( -i). Cette ccommande est par ailleurs standard et portable. GNU sedprend en charge:

sed '/marker1/,/marker2/cNew text 1\
New text 2' filename

comme une extension non standard.

Les caractères de nouvelle ligne et de barre oblique inversée doivent être échappés (avec barre oblique inverse) dans le texte de remplacement.


La commande de changement fonctionne bien pour les deux sedet les exmêmes. Merci beaucoup.
gibies

Existe-t-il un moyen d'éviter "\" et d'utiliser ici le document sedcomme dans le cas de la exsyntaxe suggérée par Bruce Ediger dans Multi-line replace .
gibies

Vous n'auriez pas besoin des barres obliques inverses si vous utilisez la rcommande décrite dans les autres réponses à cette question. Je ne sais pas comment vous utiliseriez un document ici avec sed.
G-Man dit `` Réintègre Monica ''

8

Utiliser GNU sed

Pour remplacer des lignes commençant une correspondance de ligne 3et continuant vers une correspondance de ligne 5avec New Code:

$ seq 8 | sed '/3/,/5/{/5/ s/.*/New Code/; t; d}'
1
2
New Code
6
7
8

Pour les lignes de la plage /3/,/5/, nous testons pour voir si la ligne correspond 5(ce qui signifie que c'est la dernière ligne du groupe) et, si c'est le cas, nous faisons la substitution pour insérer New Code. Si la substitution a été effectuée, la tcommande indique à sed de passer à la fin des commandes (auquel cas New Codeest imprimé). Sinon, la dcommande indique à sed de supprimer la ligne.

Toutes les autres lignes sont imprimées normalement.

Pour modifier le fichier en place, l' -ioption peut être utilisée:

sed -i.bak '/3/,/5/{/5/ s/.*/New Code/; t; d}' file

Utiliser awk

Pour faire de même avec awk:

$ seq 8 | awk '/3/,/5/{if (!f)print "New Code"; f=1; next}; 1'
1
2
New Code
6
7
8

La commande awk traite /3/,/5/spécialement les lignes de la plage . Pour les lignes de cette plage, nous testons pour voir si fest zéro (c'est-à-dire, si !fest vrai) et, si c'est le cas, nous imprimons New Codeet définissons fsur 1, puis nous ignorons le reste des commandes et passons à la nextligne.

Pour les lignes en dehors de la plage /3/,/5/, aucun saut n'est effectué et 1entraîne l'impression de la ligne. Plus en détail, 1c'est une condition. Parce qu'il 1n'est pas nul, la condition est évaluée à true. Puisqu'aucune action n'est associée à la condition, l'action par défaut est exécutée qui consiste à imprimer la ligne. C'est donc un 1raccourci pour imprimer la ligne.

Pour modifier un fichier en place, l' -i inplaceoption peut être utilisée avec GNU awk4.1 ou supérieur:

awk -i inplace '/3/,/5/{if (!f)print "New Code"; f=1; next} 1' file

cool. Je ne suis pas bon awk, pourriez-vous s'il vous plaît expliquer un peu votre awkexpression
Rahul

1
@Rahul Sure. J'ai ajouté une explication du code awk.
John1024

1
Merci John. C'est exactement ce que je cherchais.
gibies

Il est très simple de supprimer le bloc puis d'en ajouter un nouveau à la dernière ligne:sed '/3/,/4/d;/5/cNew Code' awk '/5/{print "New Code"}/3/,/5/{next}1'
Costas

1

Sur la base de la discussion ci-dessus, je trouve une solution utilisant ex

seq 15 > test1.txt
ex test1.txt << EOEX
/^7/,/^9/c
abcd
123
.xyz
hfr4
.
w!
q
EOEX
cat test1.txt

Ce qui précède donne

1
2
3
4
5
6
abcd
123
.xyz
hfr4
10
11
12
13
14
15

Merci à g-man de m'avoir informé de la commande de changement et de clarifier le point. Les deux sedet expartage la syntaxe presque similaire pour la commande de changement (également pour la commande de suppression, commande append, etc.).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.