Ziffernfolge(n)
Diese Antwort funktioniert mit jeder Anzahl von Zifferngruppen. Beispiel:
$ echo 'Num123that456are7899900contained0018166intext' \
| sed -En 's/[^0-9]*([0-9]{1,})[^0-9]*/\1 /gp'
123 456 7899900 0018166
Ausführliche Antwort.
Gibt es eine Möglichkeit, sed anzuweisen, nur erfasste Gruppen auszugeben?
Ja. Ersetzen Sie den gesamten Text durch die Erfassungsgruppe:
$ echo 'Number 123 inside text' \
| sed 's/[^0-9]*\([0-9]\{1,\}\)[^0-9]*/\1/'
123
s/[^0-9]* # several non-digits
\([0-9]\{1,\}\) # followed by one or more digits
[^0-9]* # and followed by more non-digits.
/\1/ # gets replaced only by the digits.
Oder mit einer erweiterten Syntax (weniger Anführungszeichen und die Verwendung von +):
$ echo 'Number 123 in text' \
| sed -E 's/[^0-9]*([0-9]+)[^0-9]*/\1/'
123
Um zu vermeiden, dass der Originaltext gedruckt wird, wenn es keine Nummer gibt, verwenden Sie:
$ echo 'Number xxx in text' \
| sed -En 's/[^0-9]*([0-9]+)[^0-9]*/\1/p'
- (-n) Standardmäßig wird die Eingabe nicht gedruckt.
- (/p) nur drucken, wenn eine Ersetzung erfolgt ist.
Und um mehrere Zahlen abzugleichen (und sie auch auszudrucken):
$ echo 'N 123 in 456 text' \
| sed -En 's/[^0-9]*([0-9]+)[^0-9]*/\1 /gp'
123 456
Das funktioniert für jede Anzahl von Ziffernläufen:
$ str='Test Num(s) 123 456 7899900 contained as0018166df in text'
$ echo "$str" \
| sed -En 's/[^0-9]*([0-9]{1,})[^0-9]*/\1 /gp'
123 456 7899900 0018166
Dies ist dem Befehl grep sehr ähnlich:
$ str='Test Num(s) 123 456 7899900 contained as0018166df in text'
$ echo "$str" | grep -Po '\d+'
123
456
7899900
0018166
Über \d
und Muster: /([\d]+)/
Sed erkennt nicht die ' \d ' (Abkürzung) Syntax. Die oben verwendete ascii-Entsprechung [0-9]
nicht genau gleichwertig ist. Die einzige alternative Lösung ist die Verwendung einer Zeichenklasse: '[[:digit:]]`.
Die ausgewählte Antwort verwendet solche "Charakterklassen", um eine Lösung zu finden:
$ str='This is a sample 123 text and some 987 numbers'
$ echo "$str" | sed -rn 's/[^[:digit:]]*([[:digit:]]+)[^[:digit:]]+([[:digit:]]+)[^[:digit:]]*/\1 \2/p'
Diese Lösung funktioniert nur für (genau) zwei Ziffernfolgen.
Da die Antwort innerhalb der Shell ausgeführt wird, können wir natürlich ein paar Variablen definieren, um die Antwort zu verkürzen:
$ str='This is a sample 123 text and some 987 numbers'
$ d=[[:digit:]] D=[^[:digit:]]
$ echo "$str" | sed -rn "s/$D*($d+)$D+($d+)$D*/\1 \2/p"
Doch wie bereits erläutert, ist die Verwendung eines s/…/…/gp
Befehl ist besser:
$ str='This is 75577 a sam33ple 123 text and some 987 numbers'
$ d=[[:digit:]] D=[^[:digit:]]
$ echo "$str" | sed -rn "s/$D*($d+)$D*/\1 /gp"
75577 33 123 987
Dies gilt sowohl für wiederholte Ziffernfolgen als auch für das Schreiben eines Kurzbefehls (Short(er)).