Neue Zeile mit Wert einfügen, wenn überhaupt kein Wert gefunden wird

Neue Zeile mit Wert einfügen, wenn überhaupt kein Wert gefunden wird

Ich versuche hier eine frühere Frage zu finden, die ich verwenden kann, kann aber leider meinen genauen Fall nicht finden.

Ich möchte daraus eine Ausgabe eines anderen Befehls erhalten, die so aussieht:

pattern.d
17.91
17.55
pattern.b
pattern.a
7.21
9.34
pattern.c

dazu:

pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

Ich versuche es etwas genauer zu erklären: Nach jeder Zeile, die den String "pattern" enthält, sollte immer eine Zahl stehen. Wenn nicht, würde ich gerne eine neue Zeile mit dem Wert 1000 einfügen.

Beachten Sie, dass das Muster eine „Erweiterung“ (.a .b .c .d, jedoch keine Zahlen in der „Erweiterung“) hat, die variiert und mir später dabei hilft, den Inhalt alphabetisch zu sortieren.

BEARBEITEN: Ich habe eine Antwort akzeptiert, aber für den Fall, dass jemand noch nach einer anderen Variante suchen möchte, sollte ich angeben, dass das Vorkommen von „Mustern“ variiert und es mehr als zwei oder drei aufeinanderfolgende geben kann, wie in:

pattern.a
pattern.d
pattern.c
pattern.d
pattern.b
17.91

Antwort1

Hier ist eine sedLösung, die mit jeder Eingabe funktioniert (z. B. mehrere aufeinanderfolgende Zeilen, die übereinstimmen pattern):

sed '1{                   # when on first line
x                         # exchange
s/^/1000/                 # replace the empty hold buffer with "1000"
x                         # exchange back
}
: do                      # label "do"
/pattern/{                # if the current line matches "pattern"
${                        # if we're on the last line
G                         # append hold buffer content to pattern space
b                         # go to end of script
}
n                         # otherwise print and pull in the next line
/^[[:digit:]]/!{          # if this one doesn't start with a digit
x                         # exchange
p                         # print (the pattern space is now "1000")
x                         # exchange back
b do                      # go to label "do"
}
}' infile

Damit gnu sedkann man schreiben als

sed '1{x;s/^/1000/;x};:b;/pattern/{${G;b};n;/^[[:digit:]]/!{x;p;x;bb}}' infile

Sie können etwas Ähnliches tun mit awk:

awk -vc=0 '!/^[[:digit:]]/{
if (c) {print "1000"}
}
{ if (/pattern/){c=1} else{c=0}
}
END{if (c){print "1000"}
};1' infile

d. h., setzen Sie es c=1auf passende Zeilen patternund c=0auf den restlichen Zeilen und auf jeder Zeile, die nicht mit einer Ziffer beginnt (ebenso wie im ENDBlock), prüfen Sie, ob ces gesetzt ist (oder 1– was bedeutet, dass die vorherige Zeile übereinstimmt pattern) – und drucken Sie es, wenn ja 1000.

Antwort2

sed -e '
   $!{
      /pattern\.[a-z]/N
      /\n/!b
      /\n[+-]\{0,1\}[.][0-9]\{1,\}$/b
      /\n[+-]\{0,1\}[0-9]\{1,\}\([.][0-9]*\)\{0,1\}$/b
      h;s/\(.*\n\).*/\11000/p
      g;D
   }
   /pattern\.[a-z]/a\
1000
' yourfile

Ergebnisse

pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

Arbeiten

  • Wenn wir uns nicht am Ende des Vorgangs befinden, $!{...}hängen wir die nächste Zeile an den Musterbereich an, unter der Bedingung, dass die aktuelle Zeile von Interesse ist.
  • Dann überspringen wir jede weitere Verarbeitung in folgenden Fällen: a) Kein Zeilenumbruch gefunden => kein Muster in der aktuellen Zeile. b) Eine Gleitkommazahl im Format .nnn in der zweiten Zeile. c) Eine Gleitkommazahl im Format mmm, mmm. oder mmm.nnn wird ausschließlich in der zweiten Zeile gefunden. d) Wenn keine der Möglichkeiten besteht => müssen wir am Ende der nächsten Zeile nach dem Zeilenumbruch die magische Zahl 1000 hinzufügen.

Antwort3

Wenn nie mehr als zwei aufeinanderfolgende Instanzen von vorhanden sind patternund Sie über GNU sed verfügen, dann gilt:

sed '/^pattern/ {$!N; /\n[0-9]/b; s/$/\n1000/M}' file
pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

Wie es funktioniert:

  • wenn die aktuelle Zeile mit beginnt, patterndann
    • sofern wir nicht am EOF sind, fügen Sie die nächste Zeile an
    • wenn auf den Zeilenumbruch eine Ziffer folgt (dies könnte genauer gemacht werden), dann branch out (d. h. mit der nächsten Zeile fortfahren); sonst
    • Ersetzen Sie die erste Zeile durch ein Newline-Ende und1000

Der GNU-spezifische MModifikator ermöglicht $die Übereinstimmung von entweder „ \noder $“, sodass er sowohl den „normalen“ Fall als auch den EOF-Fall behandelt, in dem keine folgende Zeile angehängt wird.

Antwort4

awkLösung:

awk '{ if ($0 ~ /pattern/) {      # if it's a `pattern` line
         if ((getline nl) > 0) {  # check if next record exists
             # if next record hasn't number - insert `1000`, otherwise - print current and next records as they are
             print ((nl !~ /^[0-9]/)? $0 ORS 1000 ORS nl: $0 ORS nl)
         } else {
             print $0 ORS 1000   # if the file ends up with pattern - insert `1000`
         } 
       } else {
          print $0  # print other record
       }
    }' file

Die Ausgabe:

pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

verwandte Informationen