Zeilenweise Änderungen in Unix

Zeilenweise Änderungen in Unix

Ich suche nach einer Möglichkeit, mit einer durch Pipes getrennten Datei in UNIX für JEDE ZEILE Folgendes zu tun, und bin nicht sicher, wo ich anfangen soll:

  1. Suchen Sie in einer Textzeile nach einem Zeichen (vermutlich mithilfe von GREP?)
  2. Wenn gefunden, fügen Sie am Ende dieser Zeile Text hinzu (mit SED?)
  3. Wenn nicht gefunden, suchen Sie nach einem anderen Zeichen in der gleichen Zeile
  4. Wenn gefunden, fügen Sie am Ende der Zeile Text hinzu, andernfalls tun Sie nichts
  5. SCHLEIFE FÜR ALLE ZEILEN IN DER DATEI

Ich bin für alle Hinweise dankbar.

Antwort1

Das ist alles sedArbeit, Sie brauchen kein zusätzliches Werkzeug:

Angenommen, Sie möchten fooam Ende einer Zeile, die ein enthält, fund baram Ende einer Zeile ohne f, aber mit einem hinzufügenb

sed '/f/{
  s/$/foo/
  b
  }
/b/s/$/bar/'

Sie können Zeilen mit "adressieren" /pattern/, sodass die folgenden Befehle nur ausgeführt werden, wenn sie das Muster enthalten. Im Beispiel lösen also nur Zeilen, die ein enthalten, fdie Ausführung des sErsetzungsbefehls aus, und b(die {}gruppieren die Befehle, sodass alles darin nur angewendet wird, wenn die Adresse übereinstimmt. Die bverzweigt zum Ende des Skripts, um das Anhängen einer weiteren Zeichenfolge für einen übereinstimmenden zu vermeiden b.

Anderer Ansatz ohne Verzweigung:

sed '/f/s/$/foo/;s/^[^f]*b[^f]*$/&bar/'

sedAls Übung können Sie dies mit etwas Wissen selbst herausfinden und man sedes ggf. anwenden.

Antwort2

Wenn Sie für beide Szenarien die gleiche Textzeichenfolge am Ende der Zeile hinzufügen möchten (zu suchende Zeichen: „X“ oder „Y“), können Sie dies wie folgt tun:

sed -e 's/[XY].*/&__ADDEDTEXT__/' yourfile

Wenn Sie hingegen je nach Zeichen separate Texte am Ende der Zeilen platzieren möchten, können Sie Folgendes tun:

sed -e '
   /X/s/$/__TEXT1__/; t
   /Y/s/$/__TEXT2__/
' yourfile

Hier verwenden wir den tBefehl (read as test), um festzustellen, ob der vorherige s///Befehl erfolgreich war, und springen zum Ende des Sed-Codes in der aktuellen Zeile. Beachten Sie auch die Syntax: /regex/s/// => wenn eine Zeile den regulären Ausdruck enthält, führen Sie die Ersetzung in der Zeile durch.

Antwort3

Perl ist auch ein nützliches Tool, mit dem sich alles problemlos in einem Durchgang erledigen lässt.

Am Beispiel von @Philippos würde ein Perl-Programm also folgendermaßen aussehen (ein Teil der Syntax ist optional und wurde zur Verdeutlichung hinzugefügt):

perl -pe '(m/f/&&s/$/foo/)||(m/b/&&s/$/bar/)' file

Dies liest filedas Ergebnis und gibt es aus. Sie können die Datei auch direkt „bearbeiten“, indem Sie -pi -eanstelle von verwenden -pe( -ibedeutet „direkt“), also:

perl -pi -e '(m/f/&&s/$/foo/)||(m/b/&&s/$/bar/)' file

Es gibt wahrscheinlich auch eine Möglichkeit, dies awkmit Ruby zu tun (das sieht fast gleich aus, pingen Sie mich an, wenn Sie Beispiele möchten), obwohl erste Tests bei mir fehlgeschlagen sind (ich bin nicht so gut in AWK), und es kann auch mit reinem Bash Spaß machen.

verwandte Informationen