Die von Ihnen angezeigte Datei enthält alle Details in einer Zeile:
name : farah age : 23 phone number : 0123 education : degree
Ich habe angenommen, dass Sie age :
usw. in den Befehl fest codieren können , aber der darauf folgende Text variiert und dass die Details möglicherweise nicht in der angegebenen Reihenfolge oder zusammenhängend sind.
Sie können Teile der Zeile mit grep
dem -o
Flag von ' extrahieren . Dadurch wird nur der übereinstimmende Teil und nicht die gesamte Zeile gedruckt.
Wenn Sie die age :
und phone number :
Teile einschließen möchten , können Sie entweder das -e
Flag verwenden, um mehrere Übereinstimmungen anzugeben, oder alternieren.
$ grep -oe 'age : [^ ]*' -e 'phone number : [^ ]*' file
age : 23
phone number : 0123
Der Ausdruck [^ ]*
bedeutet eine beliebige Anzahl von Zeichen, die kein Leerzeichen sind, sodass Zeichen nach age :
dem nächsten Leerzeichen übereinstimmen .
Ersetzen Sie file
durch den Namen der Datei, die Ihre Daten enthält. Sie können die neue Datei schreiben, indem Sie die Ausgabe mit dem >
Operator wie folgt in eine neue Datei umleiten :
grep -oe 'age : [^ ]*' -e 'phone number : [^ ]*' file > outfile
Wenn Sie dies tun, sehen Sie keine Ausgabe. Sie sollten zuerst die Ausgabe überprüfen und dann die Umleitung hinzufügen.
Hier ist das Beispiel mit Wechsel. Wir verwenden das -E
Flag, grep
um anzugeben, dass ein erweiterter regulärer Ausdruck verwendet werden soll. Die Syntax lautet (pattern1|pattern2)
- dies stimmt überein pattern1
und / oder pattern2
. Wenn eines gefunden wird, wird es gedruckt (unabhängig davon, ob das andere gefunden wird oder nicht). Ich verwende jetzt die +
Bedeutung mindestens eines der vorhergehenden Zeichen, anstatt *
null oder mehr des vorhergehenden Zeichens zu bedeuten. In diesem Zusammenhang funktionieren beide gleich gut.
$ grep -Eo '(age : [^ ]+|phone number : [^ ]+)' file
age : 23
phone number : 0123
Wenn Sie die age :
und phone number:
Teile weglassen möchten , können Sie das -P
Flag verwenden, um grep
nach Perl-kompatiblen regulären Ausdrücken zu fragen . Dies unterstützt den Wechsel und auch eine Möglichkeit, Text nach einem bestimmten Muster abzugleichen:
$ grep -Po '(age : \K[^ ]+|phone number : \K[^ ]+)' file
23
0123
Wenn Sie den Text anders formatieren möchten, können Sie beispielsweise Folgendes verwenden sed
:
$ sed -r 's/.*(age) : ([^ ]*).*(phone number) : ([^ ]*).*/\1:\2 | \3:\4/' file
age:23 | phone number:0123
Dies hängt davon ab , ob Sie age
vorher phone number
kommen. Passen Sie dies entsprechend an, wenn dies nicht der Fall ist. Wenn Sie sich nicht auf die Reihenfolge verlassen können, können Sie diesen sehr komplizierten Befehl verwenden:
$ sed -r 's/(.*)(phone number : [^ ]+)(.*) .*/\2 \1\4/; s/(phone number) : ([^ ]+) .*(age) : ([^ ]+).*/\1: \2 | \3: \4/' file
phone number: 0123 | age: 23
Dadurch wird die Zeile neu angeordnet, sodass der phone number :
Abschnitt in jeder Zeile an erster Stelle steht. Anschließend wird ein zweiter Austausch durchgeführt, um die gewünschten Details auszuwählen. Die hier verwendete Technik verdanke ich dieser Antwort von Muru .
Hinweise zu sed
Befehlen, die in den vorherigen Erläuterungen nicht behandelt wurden
-r
Verwenden Sie erweiterte Regex für besser lesbare Befehle (GNU sed
versteht -E
mit der gleichen Bedeutung)
s/old/new/
ersetzen old
durchnew
(pattern)
Speichert, pattern
um später mit \1
oder \2
usw. zu referenzieren (entsprechend der Reihenfolge von links nach rechts, in der die Erfassungsgruppen auftreten - beachten Sie, dass sed
nur bis zu 7 davon enthalten sind!).
.
Ein beliebiges Zeichen steht daher .*
für eine beliebige Anzahl beliebiger Zeichen.
;
trennt Befehle wie in der Shell.