Wie verwende ich den Grep-Befehl, um einen Teil der Zeichenfolge wie unten zu erhalten?
Zeichenfolge:
orange:"orange", red:"apple", purple:"grape", yellow:"banana", green:"watermelon"
red:"strawberries", yellow:"lemon"
Was ich möchte:
red:"apple" yellow:"banana"
red:"strawberries" yellow:"lemon"
Ich habe Folgendes versucht:
grep -oP '(red:\"[^\"]*).*(yellow:\"[^\"]*)'
Antwort1
Das .*
in der Mitte passt alles an, also den purple:"grape"
Teil. Stattdessen (vorausgesetzt, Sie möchten bei GNU grep bleiben) würde ich jeden Teil einzeln mit der (foo|bar)
„ODER“-Konstruktion abgleichen.
grep -oP '(red|yellow):\"[^\"]*"'
NB: Ich musste das schließende hinzufügen "
. Außerdem müssen Sie das nicht maskieren "
, Sie können also verwenden
grep -oP '(red|yellow):"[^"]*"'
Auf jeden Fall gibt Ihnen das
red:"apple"
yellow:"banana"
dann die Zeilen mit Abstand dazwischen zu verbinden,
grep -oP '(red|yellow):"[^"]*"' | paste -sd ' ' -
Ehrlich gesagt würde ich sed
stattdessen natürlich verwenden.
sed -n 's/.*\(red:"[^"]*"\).*\(yellow:"[^"]*"\).*/\1 \2/p'
Antwort2
grep
extrahiert normalerweise keinen Inhalt aus den Zeilen. Es p
druckt die Zeilen aus, die einem r
regulären e
Ausdruck entsprechen ( g
es ist allgemein nach dem g/re/p
ed
Befehl benannt).
Einige Implementierungen wie GNU grep
, das Sie anscheinend verwenden, können -o
einige dieser Funktionen jedoch als Erweiterung ausführen.
pcregrep
geht sogar noch weiter. Es -o
kann ein optionales numerisches Argument annehmen, um den Inhalt einer Erfassungsgruppe auszugeben, anstatt des gesamten übereinstimmenden Teils der Zeile.
pcregrep -o1 -o2 --om-separator=' ' '(red:"[^"]*").*(yellow:"[^"]*")'
Die Möglichkeiten sind immer noch begrenzt.
Um Informationen aus der Zeile zu extrahieren und weitere Transformationen durchzuführen, benötigen Sie stattdessen einen Texttream s
- ed
Itor, wie andere hier gezeigt haben.
Antwort3
Sie können es tatsächlich mit grep
so tunvorgeschlagen von Sparhawk, oder mit dem fast identischen:
$ echo 'red:"apple", purple:"grape", yellow:"banana"' |
grep -oP '(red|yellow):".+?"' | perl -00pe 's/\n/ /'
red:"apple" yellow:"banana"
Persönlich würde ich es wahrscheinlich so machen perl
:
$ echo 'red:"apple", purple:"grape", yellow:"banana"' |
perl -F, -ane 'map{print if /red|yellow/}@F'
red:"apple" yellow:"banana"