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 grepdem -oFlag 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 -eFlag 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 filedurch 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 -EFlag, grepum anzugeben, dass ein erweiterter regulärer Ausdruck verwendet werden soll. Die Syntax lautet (pattern1|pattern2)- dies stimmt überein pattern1und / 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 -PFlag verwenden, um grepnach 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 agevorher phone numberkommen. 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 sedBefehlen, die in den vorherigen Erläuterungen nicht behandelt wurden
-rVerwenden Sie erweiterte Regex für besser lesbare Befehle (GNU sedversteht -Emit der gleichen Bedeutung)
s/old/new/ersetzen olddurchnew
(pattern)Speichert, patternum später mit \1oder \2usw. zu referenzieren (entsprechend der Reihenfolge von links nach rechts, in der die Erfassungsgruppen auftreten - beachten Sie, dass sednur bis zu 7 davon enthalten sind!).
.Ein beliebiges Zeichen steht daher .*für eine beliebige Anzahl beliebiger Zeichen.
; trennt Befehle wie in der Shell.