2016-08-06 10 views
0

Ich möchte ein Spaltenname-Wert-Paar aus einer INSERT-Anweisung entfernen und in eine andere INSERT-Anweisung verschieben. Ich habe ungefähr einhundert verschiedene Dateien, die diese Art von Format haben (obwohl das Format von Datei zu Datei leicht variieren kann, zum Beispiel haben einige Benutzer die gesamte INSERT-Anweisung in eine Zeile geschrieben).Bash Ausschneiden und Einfügen SQL-Insert-Anweisung

INPUT

INSERT INTO table1 (
    col1, 
    col2 
) 
VALUES (
    foo, 
    bar 
); 

INSERT INTO table2 (
    col3, 
    col4_move_this_one, 
    col5 
) 
VALUES (
    john, 
    doe_move_this_value, 
    doe 
); 

OUTPUT

INSERT INTO table1 (
    col1, 
    col4_move_this_one, 
    col2 
) 
VALUES (
    foo, 
    doe_move_this_value, 
    bar 
); 

INSERT INTO table2 (
    col3, 
    col5 
) 
VALUES (
    john, 
    doe 
); 

Im Allgemeinen mit dem obigen Format, das ich dachte ich sed und Katze in einem Skript verwenden könnte Zeilennummern jeder Zeile zu finden bewegt und dann werden bewege es, so etwas.

for file in *; do 
    line_number=$(cat -n ${file} | sed some_statement | awk to_get_line_number) 
    # etc... 
done 

... aber vielleicht kann euch eine clevere Art und Weise empfehlen, die auch auf einer Linie Aussage ist, wenn die INSERT funktionieren würde.

+0

Bitte geben Sie eine Datenprobe und das Ergebnis, das Sie benötigen .. – scaisEdge

+0

@scaisEdge Edited die Post mit Eingangs- und Ausgangstestfall. – dood

Antwort

1

GNU awk für echte Mehrdimensionale Arrays, 3. ARG Match(), multi-char RS und \ s/\ S syntaktischen Zucker:

$ cat tst.awk 
BEGIN { RS="\\s*);\\s*" } 
match($0,/(\S+\s+){2}([^(]+)[(]([^)]+)[)][^(]+[(]([^)]+)/,a) { 
    for (i in a) { 
     gsub(/^\s*|\s*$/,"",a[i]) 
     gsub(/\s*\n\s*/,"",a[i]) 
    } 
    tables[NR] = a[2] 
    names[NR][1]; split(a[3],names[NR],/,/) 
    values[NR][1]; split(a[4],values[NR],/,/) 
} 
END { 
    names[1][3] = names[1][2] 
    names[1][2] = names[2][2] 
    names[2][2] = names[2][3] 
    delete names[2][3] 

    values[1][3] = values[1][2] 
    values[1][2] = values[2][2] 
    values[2][2] = values[2][3] 
    delete values[2][3] 

    for (tableNr=1; tableNr<=NR; tableNr++) { 
     printf "INSERT INTO %s (\n", tables[tableNr] 
     cnt = length(names[tableNr]) 
     for (nr=1; nr<=cnt; nr++) { 
      print " " names[tableNr][nr] (nr<cnt ? "," : "") 
     } 
     print ")" 

     print "VALUES (" 
     cnt = length(values[tableNr]) 
     for (nr=1; nr<=cnt; nr++) { 
      print " " values[tableNr][nr] (nr<cnt ? "," : "") 
     } 
     print ");\n" 
    } 
} 

.

$ awk -f tst.awk file 
INSERT INTO table1 (
    col1, 
    col4_move_this_one, 
    col2 
) 
VALUES (
    foo, 
    doe_move_this_value, 
    bar 
); 

INSERT INTO table2 (
    col3, 
    col5 
) 
VALUES (
    john, 
    doe 
); 
1

A GAWK Version, die auf gensub ‚s Rückreferenzierung Funktion beruht und stark auf regex.

$ cat > test.awk 
BEGIN { 
    RS=" *) *; *"   # set RS to ");" and prepare to space as well 
    ORS=");\n" 
} 

{ 
    sub(/^[ \n]*/,"")  # remove emptiness before second INSERT 
} 

$0 ~ /^INSERT/ && NR==1 { 
    a=$0     # store the first INSERT 
} 

$0 ~ /^INSERT/ && NR==2 { # store the second and use gensub to 
    b=$0     # find the second variables in INSERT and VALUES 
    split(gensub(/(INSERT|VALUES)[^\(]*\(([ \n]*[^,]*,){1}[ \n]*([^,]*)[^\)]*\)*[ \n]*/,"\\3 ","g"),c," ") 
} 

END {      # print first INSERT with second variables in place 
          # and second INSERT with variables removed 
    print gensub(/((INSERT|VALUES)[^\(]*\((([ \n]*)[^,]*,){1})/,"\\1\\4"c[++i]",\\5","g",a) 
    print gensub(/((INSERT|VALUES)[^\(]*\(([ \n]*[^,]*,){1})[ \n]*[^,]*,/,"\\1 ","g",b) 
} 

Diese Lösung setzt voraus, dass Variablen die zweiten Variablen in der zweiten INSERT nach Keywords zu kopieren sind INSERT und VALUES und dass sie in der ersten INSERT an den gleichen Orten hinzugefügt. Lösung ist Platz und \n freundlich, aber nicht unterstützt \t, leicht zu beheben Ich nehme an.

$ awk -f test.awk file 
INSERT INTO table1 (
    col1, 
    col4_move_this_one, 
    col2 
) 
VALUES (
    foo, 
    col4_move_this_one, 
    bar 
); 
INSERT INTO table2 (
    col3, 
    col5 
) 
VALUES (
    john, 
    doe 
); 
Verwandte Themen