Führen Sie sed-Operationen an bestimmten Zeilennummern durch

8

Ich frage mich, ob es eine einfache Möglichkeit gibt, bestimmte Leitungen mit vorab zugewiesenen Zeilennummern zu bearbeiten.

Angenommen, ich möchte die 1., 7., 14. und 16. Zeile einer Datei ausgeben, was ich einfach tun kann

sed -n '1p;7p;14p;16p' input_file

Dies wird jedoch komplizierter, wenn die Operation nicht nur gedruckt wird und ich nicht viermal denselben langen Befehl schreiben möchte (und ja, ich weiß, dass ich diesen langen sed-Befehl konstruieren kann, indem ich dieselbe bash-Variable viermal ersetze, aber das ist nicht ideal genug ...), dh

sed -n '1{long_command};7{long_command};14{long_command};16{long_command}' input_file

Gibt es eine Möglichkeit, den Vorgang in diesen bestimmten Zeilen meiner Datei auszuführen? Ich erwarte so etwas wie

sed -n '1,7,14,16p'

was in der aktuellen Form sicherlich nicht funktionieren wird.

Jede Hilfe wird geschätzt. "Nein, das ist nicht möglich." mit Erklärungen ist auch eine Antwort, die ich akzeptieren werde.

Weijun Zhou
quelle
es ist einfach mitawk
RomanPerekhrest

Antworten:

11

Sie können Zweige verwenden:

sed '
  1b1
  7b1
  14b1
  16b1

  # for the rest to be left alone, branch off (or delete them with "d"):
  b

  :1
  long_command'

(Beachten Sie, dass Sie auch einige 20,25b1Zeilenbereiche hinzufügen oder /re/b1Zeilen einschließen können, die mit den übereinstimmen re).

Oder Sie könnten verwenden awk:

awk 'NR == 1 || NR == 7 || ... {stuff}'

Oder mit einem Hash:

awk -v l=1,7,14,16 '
  BEGIN{split(l, a, ","); for (i in a) lines[a[i]]}

  NR in lines {stuff}'

(oder BEGIN{lines[1]lines[7]lines[14]lines[16]}wenn es nicht zu viele gibt)

Stéphane Chazelas
quelle
Vielen Dank, ich habe nie an Zweige gedacht ... Es scheint einfach das ideale Werkzeug für diesen Fall zu sein.
Weijun Zhou
Wie verwendet man solche Zweige in sed mit einem Suchmuster? Wie möchte ich sagen, dass ich ein Muster nach der n-ten Zeile abgleichen oder löschen möchte?
Qodeninja
3

Kehren Sie einfach Ihre Auswahl um und löschen Sie sie:

sed '2,6d;8,13d;15d;17,$d;long_command'
Philippos
quelle
Dies ist auch eine gute Lösung, wenn auch etwas schwieriger für den Umgang mit Zeilennummern, die beispielsweise von stdin gelesen werden.
Weijun Zhou
1

Erste Variante:

Sie können diesen Trick verwenden:

sed -nf <(printf '%dp\n' 1 7 14 16)

-f Skriptdatei - Fügt den Inhalt der Skriptdatei zu den auszuführenden Befehlen hinzu.

Testen

seq 1 20 | sed -nf <(printf '%dp\n' 1 7 14 16)

Ausgabe

1
7
14
16

Zweite Variante:

Am Anfang wird das Auxiliary sedverwendet, um nur benötigte Zeilen aus der Datei zu filtern, und diese Zeilen werden dann sedmit dem Befehl long an die Hauptleitung weitergeleitet .

sed -n '1p; 7p; 14p; 16p' input.txt | sed 'long command'
MiniMax
quelle