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 sed
Lö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 sed
kann 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=1
auf passende Zeilen pattern
und c=0
auf den restlichen Zeilen und auf jeder Zeile, die nicht mit einer Ziffer beginnt (ebenso wie im END
Block), prüfen Sie, ob c
es 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 pattern
und 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,
pattern
dann- 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
b
ranch out (d. h. mit der nächsten Zeile fortfahren); sonst - Ersetzen Sie die erste Zeile durch ein Newline-Ende und
1000
Der GNU-spezifische M
Modifikator ermöglicht $
die Übereinstimmung von entweder „ \n
oder $
“, 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