2017-09-10 1 views
0

Ich bin mir nicht sicher, warum das nicht funktioniert. Hier ist die Regex 'text\' => '.*?' und ich möchte estrenos und cine im folgenden fiesen Text mit grep oder sed fangen. Hier ist, was ich in Grep versuchtUmwandlung Regex in sed oder Grep Regex

echo "sadsa d{        'text' => 'cine',        'indices' => [           111,           116           ]       },       {        'text' => 'estrenos',        'indices' => [ sSADW" | grep -Eo "'text\' => '.*?'," 

Antwort

3

Nur awk verwenden:

$ awk -v RS='}' -F\' '{print $4}' file 
cine 
estrenos 

, die mit jedem awk in jeder Schale arbeitet auf jede UNIX-Box. Es wird auch funktionieren, egal was der Leerraum ist, so dass es funktioniert, ob Ihre Eingabe in einer Zeile oder über mehrere Zeilen verteilt ist und egal wie viele Leerzeichen oder Tabs irgendwo in jeder Zeile vorkommen.

Hier ist, wie es funktioniert:

awk behandelt alle Eingaben als Datensätze in Felder getrennt. Ihre Eingabe (mit Leerzeichen zur besseren Lesbarkeit komprimiert):

sadsa d{ 'text' => 'cine', 'indices' => [ 111, 116 ] }, { 'text' => 'estrenos', 'indices' => [ sSADW 

hat eindeutig { ... } Datensätze:

Aufnahme 1:

{ 'text' => 'cine', 'indices' => [ 111, 116 ] } 

Record 2:

{ 'text' => 'estrenos', 'indices' => [ sSADW 

so können wir setzen der Record Separator zu } (mit -v RS='}'). Ich gehe davon aus, dass deine letzte Aufnahme wirklich in einer } enden wird, aber wenn das nicht gut ist, dann behandelt awk das Ende der Datei wie das Ende eines Datensatzes. Wir können den Text vor dem { s (dh "sadsa d" vor dem ersten Datensatz und "," zwischen den 2 Datensätzen ignorieren - das wird wirklich als Teil des ersten Feldes behandelt, aber wir verwenden dieses Feld für nichts, also ist es irrelevant

die oben genannten 2 Datensätze so gegeben, wenn wir sie in die Felder bei jedem ' (mit -F\') geteilt dann erhalten wir:.

$ awk -v RS='}' -F\' '{for (i=1; i<=NF;i++) print "Record Nr", NR, "Field Nr", i, "Field Contents: <" $i ">"; print "----" 
}' file 
Record Nr 1 Field Nr 1 Field Contents: <sadsa d{ > 
Record Nr 1 Field Nr 2 Field Contents: <text> 
Record Nr 1 Field Nr 3 Field Contents: < => > 
Record Nr 1 Field Nr 4 Field Contents: <cine> 
Record Nr 1 Field Nr 5 Field Contents: <, > 
Record Nr 1 Field Nr 6 Field Contents: <indices> 
Record Nr 1 Field Nr 7 Field Contents: < => [ 111, 116 ] > 
---- 
Record Nr 2 Field Nr 1 Field Contents: <, { > 
Record Nr 2 Field Nr 2 Field Contents: <text> 
Record Nr 2 Field Nr 3 Field Contents: < => > 
Record Nr 2 Field Nr 4 Field Contents: <estrenos> 
Record Nr 2 Field Nr 5 Field Contents: <, > 
Record Nr 2 Field Nr 6 Field Contents: <indices> 
Record Nr 2 Field Nr 7 Field Contents: < => [ sSADW 
> 
---- 

so, wie Sie den Wert, den Sie wollen, ist sehen immer nur das vierte Feld von jedem Datensatz

+0

Können Sie es bitte brechen? – user3639557

+1

Ich habe eine Erklärung hinzugefügt, lassen Sie mich wissen, wenn Sie irgendwelche Fragen haben. –

+1

Hölle einer Erklärung. zu gut. Und Ed, denkst du nicht, dass die Verwendung von Extended Grep eine gute Option wäre, da Grep hauptsächlich für diesen Zweck gedacht ist. Hier für z. 'egrep -o '' text '=>' \ w + '" Datei | geschnitten -d \ '-f4'? Wenn nicht, warum? – batMan

0

Entfernen Sie die Escape-Zeichen für das einfache Angebot. Allerdings ist da der erweiterte regexp nicht nicht gierigen Matching unterstützen Sie wollen wahrscheinlich statt Perl verwenden:

grep -Po "'text' => '.*?', 
+0

Nice! Aber das gibt 'text' => 'cine'' zurück, aber ich möchte' cine' bekommen – user3639557

+1

@ user3639557 du kannst das ändern zu 'grep -Po '' text '=>' \ K [^ '] +" 'oder' grep -Po '' text '=>' \ K [^ '] + (? =',) "' für Robustheit – Sundeep

+0

Sie sollten erwähnen, dass es nur GNU grep ist und das laut GNU grep man page '-P 'ist" sehr experimentell "so YMMV mit es zu verwenden. –

0

tr + sed Ansatz:

(vorausgesetzt, Ihre Eingabe von Text in Variable $s ist)

sed -n "s/.*'text' => '\([^']*\)'.*/\1/p" <(tr ',' '\n' <<< "$s") 

Der Ausgang:

cine 
estrenos