2017-12-11 1 views
1

Könnten Sie mir helfen, korrekte Regex in bash zu erstellen?Endabgleich nach dem ersten Auftreten eines Wortes - Bash Regex

Was ich tun muss, ist jede Tabelle Definition von Struktur zu extrahieren wie:

OID: 123 
    Name: tab1 
    CREATE TABLE tab1 (
     ... 
     ); 

    OID: 456 
    Name: tab2 
    CREATE TABLE tab2 (
     ... 
     ); 

    OID: 789 
    Name: tab3 
    CREATE TABLE tab3 (
     ... 
     ); 

vorbereitet eine Zeile Format:

OID: 123 Name: tab1 CREATE TABLE tab1 (...); OID: 456 Name: tab2 CREATE TABLE tab2 (...); OID: 789 Name: tab3 CREATE TABLE tab3 (...); 

Ich habe den gesamten Text zwischen den Wörtern Name und OID zu bekommen. Ich schrieb eine einfache Schleife, die spezifische Regex für jeden Tabellennamen vorbereitete, aber ich habe ein Problem mit der Übereinstimmung.

Für jede Tabelle meine regex Name ist so etwas wie:

(Name: tab2 .*?)(OID: .*) 

Mein Ergebnis ist:

Name: tab2 CREATE TABLE tab2 (...) 

ich oben regex in Online regex Simulator getestet und es funktioniert. Ich extrahiere nur die erste Gruppe aus der vollständigen Übereinstimmung. Batch Regex gruppiert es nicht ordnungsgemäß. Ich denke Batch weiß es nicht? (Null oder ein Vorkommen des vorhergehenden Elements). Ich habe kein Ergebnis mit der obigen Regex in bash.

Mein bash Befehl ist so etwas wie:

#!/bin/bash 
tables_definition=$(less tables_definition.txt) 
regex="(Name: tab2 .*?)(OID: .*)" 

    if [[ $tables_definition =~ $regex ]]; 
     then 
     object_definition="${BASH_REMATCH[1]}"  

     #do something 
    fi 

Bitte helfen.

+0

können Sie den bash-Befehl posten, den Sie verwenden? –

+0

hat gerade meinen Post bearbeitet – MrF

+2

'. *?'ist ein Problem - POSIX ERE (der Standard, dem bashs Regexes entsprechen) hat keine nicht-gierigen Klumpen. (Die Regex-Engine ist nicht wirklich in bash integriert, sondern wird von der C-Bibliothek Ihres Betriebssystems bereitgestellt, sodass die Implementierung von Plattform zu Plattform ein wenig variieren kann. Die verwendeten Aufrufe sind jedoch zur Implementierung des ERE-Standards erforderlich eine plattformspezifische Erweiterung). –

Antwort

1

Bashs Regexen unterstützen keine "sparsamen Quantifier".

Wie wäre es mit grep mit PCRE?

grep -Po '(?<=Name: tab.).*?(?= OID: .*|$)' 

Es gibt alle drei Definitionen aus Ihrer einzeiligen Zeichenfolge zurück.

+0

Funktioniert nicht für mich. Ich erhielt: 'pcregrep: Fehler in der Befehlszeilenregex bei Offset 31: Lookbehind Behauptung ist nicht feste Länge Darüber hinaus ist es wichtig, diese Definitionen eins nach dem anderen zu bekommen. Deshalb habe ich es in eine Schleife gelegt. – MrF

+0

@MrF: Sie haben wahrscheinlich eine nicht feste Länge im '(? <= ...)' Teil verwendet. Sie können die Definitionen immer einzeln von grep lesen. – choroba

1

Mit awk:

$ awk 'BEGIN{RS="";ORS=OFS=" "}{$1=$1;print}' file 
OID: 123 Name: tab1 CREATE TABLE tab1 (...); OID: 456 Name: tab2 CREATE TABLE tab2 (...); OID: 789 Name: tab3 CREATE TABLE tab3 (...); 

Das Newline auch fehlt (aufgrund ORS=" "). Fügen Sie bei Bedarf am Ende des Programms END{print "\n"} hinzu.

0

Eine Bash-Lösung. Die Eingabedatei die Tabellendefinition in einem Zeilenformat (nicht notwendigerweise) enthält:

shopt -s extglob 

    table_definition=$(cat table_definition.txt) 
    table_definition=${table_definition//OID: +([[:digit:]]) Name: tab+([[:digit:]])/} 
    table_definition=${table_definition//; /;\\n} 

    echo -e $table_definition 

Der erste Parameter Substitution löscht alle OID: xxx Name: tabx, fügt der zweite eine neue Zeile für alle Semikolons.

Der Ausgang:

CREATE TABLE tab1 (...); 
    CREATE TABLE tab2 (...); 
    CREATE TABLE tab3 (...); 

Wenn die Eingabedatei keine Verwendung oneliner ist

table_definition=$(cat table_definition2.txt | tr -d "\n" | tr -s ' ') 

zu Zeilenumbrüche zu löschen und die Zuschnitte sqeeze.

Verwandte Themen