2016-08-08 56 views
0

Ich möchte die erste Instanz einer Zeichenfolge pro Zeile in Linux extrahieren. Ich versuche gerade grep, aber es liefert alle Instanzen pro Zeile. Darunter möchte ich die Strings (Zahlen und Buchstaben) nach "tn =" ... aber nur die erste Menge pro Zeile. Die tatsächlichen Zeichen könnten irgendeine Kombination von Zahlen oder Buchstaben sein. Und hinter ihnen ist Platz. Es gibt auch einen Raum vor dem tn =extrahieren erste Instanz pro Zeile (vielleicht grep?)

folgende Datei Gegeben:

hello my name is dog tn=12g3 fun 23k3 hello tn=1d3i9 cheese 234kd dks2 tn=6k4k ksk 

1263 chairs are good tn=k38493kd cars run vroom it95958 tn=k22djd fair gold tn=293838 tounge 

gewünschte Ausgabe:

12g3 

k38493 
+0

Haben Sie wirklich den 'kd' vom Ende der' tn = k38493kd' in Ihrer zweiten Zeile der Ausgabe entfernt werden? Wenn dies der Fall ist, klären Sie Ihre Anforderungen, wenn Sie Ihre erwartete Ausgabe nicht korrigieren. –

Antwort

0

geteilt einfach die Eingabe in tn= -separators und die zweite Auswahl. Dann spaltete wieder alles auf den ersten Platz zu bekommen:

$ awk -F"tn=" '{split($2,a, " "); print a[1]}' file 
12g3 
k38493kd 
+0

In Bezug auf das Multi-Char-FS sollte jedes POSIX-kompatible awk das unterstützen. Das GNU-spezifische Verhalten in Bezug auf RS. –

+0

Vielen Dank! das funktioniert perfekt! – olivertheheavy

+1

@TomFenech oh, gut zu wissen! Ich sehe es ist in der [POSIX Awk-Seite] (http://pubs.opengroup.org/onlinepubs/009695399/utilities/awk.html) beschrieben. Danke – fedorqui

2

Hier ein Weg, können Sie es tun, wenn Sie GNU grep haben, die (meist) unterstützt Perl Compatible Regular Expressions mit -P. Auch die Nicht-Standard-Switch -o wird verwendet, um nur den Teil drucken Sie das Pattern-Matching, anstatt der ganzen Linie:

grep -Po '^.*?tn=\K\S+' file 

Das Muster entspricht dem Anfang der Zeile ^, gefolgt von beliebigen Zeichen .*?, wo die ? macht das Spiel nicht gierig. Nach dem ersten Spiel von tn= "\K" "tötet" den vorherigen Teil, so dass Sie nur mit dem Bit, das Sie interessiert sind: ein oder mehrere Nicht-Leerzeichen Zeichen \S+.

Wie in Ed's answer möchten Sie möglicherweise ein Leerzeichen vor tn hinzufügen, um versehentliches Übereinstimmen mit etwas wie footn=... zu vermeiden. Vielleicht möchten Sie auch etwas wie \w verwenden, um "Wort" -Zeichen zu entsprechen (entspricht [[:alnum:]_]).

+0

Ah schön, ich spielte mit 'grep -Po '(? <= Tn =) \ w' file', das funktionierte aber alle Treffer in einer Zeile. Ich mag, wie das funktioniert. – fedorqui

0
$ awk 'match($0,/ tn=[[:alnum:]]+/) {print substr($0,RSTART+4,RLENGTH-4)}' file 
12g3 
k38493kd 
+0

Uhms, aber was ist, wenn die Zeile mit 'tn = 23' beginnt? Der führende Platz in der Regexp wird nicht übereinstimmen. Es lohnt sich wahrscheinlich, ['\ <'] (https://www.gnu.org/software/gawk/manual/html_node/GNU-Regexp-Operators.html) zu verwenden und "awk" ($ 0,/\ <) zu sagen tn = [[: alnum:]] + /) {drucke substr ($ 0, RSTART + 3, RLENGTH-3)} 'Datei'. – fedorqui

+1

Das OP sagte 'Es gibt auch ein Leerzeichen vor dem tn ='. Verwendung von '\ <' würde es unnötig gawk-spezifisch machen. –