3 votes

Faire correspondre un motif, insérer le motif, jusqu'à la prochaine correspondance.

J'ai du mal à formater un fichier en fonction de la sortie souhaitée, à l'aide de bash outils. En voici un exemple :

address="192.168.1.1"
portid="443"
portid="2000"
address="192.168.1.2"
portid="443"
portid="2000"

En fait, ce que j'essaie de faire, c'est de rechercher un motif (dans ce cas, toute la ligne d'adresse IP) et de l'ajouter à chaque ligne suivante jusqu'à la prochaine correspondance (avant l'adresse IP suivante). Le résultat souhaité est le suivant :

address="192.168.1.1"portid="443"
address="192.168.1.1"portid="2000"
address="192.168.1.2"portid="443"
address="192.168.1.2"portid="2000"

Comment puis-je y parvenir en utilisant grep , awk o sed ?

10voto

RavinderSingh13 Points 29608

Considérant que votre fichier réel est le même que celui de l'exemple Input_file :

awk '/address/{val=$0;next} {print val $0}'  Input_file

2voto

Akshay Hegde Points 12930

Entrée

[akshay@localhost tmp]$ cat file
address="192.168.1.1"
portid="443"
portid="2000"
address="192.168.1.2"
portid="443"
portid="2000"

Sortie

[akshay@localhost tmp]$ awk '/portid/{print a $0; next}/address/{a=$0}' file
address="192.168.1.1"portid="443"
address="192.168.1.1"portid="2000"
address="192.168.1.2"portid="443"
address="192.168.1.2"portid="2000"

2voto

simlev Points 698

1. sed

sed -n 's/address/&/;Ta;h;d;:a;G;s/\(.*\)\n\(.*\)/\2\1/;p' file

Certes, c'est plus obscur que awk o perl qui aurait plus de sens ici, et dont le code est assez explicite.

s/address/&/;           test (substitute with self) for address
Ta;                     if false, got to label a
h;                      (if true) put the line in the hold buffer
d;                      delete the line from the pattern space
:a;                     set the label a
G;                      append the hold buffer to the pattern space (current line)
s/\(.*\)\n\(.*\)/\2\1/  swap around the newline, so the hold buffer contents
                        are actually prepended to the current line
p                       print the pattern space

Mise à jour : potong La suggestion de l'auteur est à la fois plus courte et plus facile à suivre :

sed '/^address/h;//d;G;s/\(.*\)\n\(.*\)/\2\1/' file

2. awk

awk '/address/{a=$0} /portid/{print a$0}' file

3. perl

perl -lane '$a=$_ if /address/;print $a.$_ if /portid/' file

1voto

stevesliva Points 1340

Réponse sélective. Il faut utiliser l'espace d'attente avec précaution.

*`sed -n -e '/addr/h;/portid/{x;G;s/\nportid/portid/;p;s/portid.//;h;}'`**

Explication :

  • sed -n - n'imprimer que lorsqu'on lui demande explicitement de le faire
  • /addr/h - sauvegarder les lignes d'adresse dans l'espace d'attente
  • /portid/{...} - sur chaque ligne correspondant à portid, faites ceci :
    • x récupérer la ligne addr de l'espace de maintien, mettre la ligne portid dans l'espace de maintien à la place.
    • G ajouter la ligne portid à la ligne addr
    • s/\nportid/portid/ - supprimer le saut de ligne au début de la ligne portid
    • p imprimer les lignes combinées
    • s/portid.*// retirer la substance portive de la ligne combinée
    • h sauvegarder la ligne d'adresse dans l'espace d'attente à nouveau
  • Bien sûr, si l'entrée est vraiment aussi simple, vous pouvez condenser les endroits où j'ai utilisé addr o portid à juste a y p mais sed est assez obscure.

Sortie :

$ sed -n -e '/addr/h;/portid/{x;G;s/\\nportid/portid/;p;s/portid.\*//;h}' addr.txt 
address="192.168.1.1"portid="443"
address="192.168.1.1"portid="2000"
address="192.168.1.2"portid="443"
address="192.168.1.2"portid="2000"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X