
Ich habe ein Bash-Skript, das Tabelleneinträge validiert. Der endgültige Ausgabewert ist $out, der in eine SQL INSERT-Anweisung eingefügt wird, die dann an /tmp/crew.txt angehängt wird. Während $out eindeutig durch Kommas getrennt ist, stehen in der resultierenden INSERT-Anweisung in /tmp/crew.txt keine Kommas zwischen den Werten. Warum ist das so und wie kann es behoben werden, damit ich in /tmp/crew.txt durch Kommas getrennte Werte habe?
#!/bin/bash
out=290,'02:20:00','02:40:00',20.5,NULL
echo "${out:1}"
290,'02:20:00','02:40:00',20.5,NULL
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES ("${out:1}");" >> /tmp/crew.txt
vi /tmp/crew.txt
INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES ( 290 '02:20:00' '02:40:00' 20 NULL);
Daher sollte das Ergebnis in /tmp/crew.txt lauten:
INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES ( 290,'02:20:00','02:40:00',20,NULL);
Antwort1
Hypothese: Ihre IFS
Variable enthält ,
. Das Skript ändert nichts IFS
, daher muss der nicht standardmäßige Wert in der Umgebung vorhanden gewesen sein.
Diese andere Antwortmir ist aufgefallen, dass Sie die Anführungszeichen in einer Zeile entfernt haben ${out:1}
, die folgendermaßen aussieht:
echo "foo"${out:1}"bar"
Variable ohne Anführungszeichendurchläuft eine Worttrennung und Dateinamengenerierung. Die Worttrennung erfolgt durch IFS
. Das nicht in Anführungszeichen gesetzte Wort ${out:1}
wird in mehrere Wörter aufgeteilt, echo
erhält mehrere Argumente und gibt diese durch einzelne Leerzeichen getrennt aus (weil dies das Ergebnis ist echo
, unabhängig vom IFS
).
Wenn Sieprintf
wie empfohlenwäre es einfacher zu erkennen, ob die Variable in Anführungszeichen steht:
printf 'INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (%s);\n' "${out:1}"
Und wenn Sie die Variable nicht in doppelte Anführungszeichen setzen würden, printf
würde sie mehrere Argumente erhalten ${out:1}
und mehrere Zeilen generieren. Dann sollte es ziemlich offensichtlich sein, dass eine gewisse Aufteilung erfolgt. Die Verwendung von echo
that zur Verkettung seiner Argumente verschleiert diese Tatsache bis zu einem gewissen Grad.
Separate Probleme:
Die gewünschte Ausgabe lässt darauf schließen, dass Sie nichts möchten,
"${out:1}"
jedoch" $out"
mit einem führenden Leerzeichen.Um einfache Anführungszeichen in die Variable aufzunehmen, sollten Sie sicherstellen, dass die Shell sie nicht entfernt. Escapen Sie sie (danke an denbereits erwähnte Antwort) oder setzen Sie sie in doppelte Anführungszeichen:
out="290,'02:20:00','02:40:00',20.5,NULL"
Antwort2
Warum ist das so und wie kann es behoben werden?
Durch Entfernen der Echo-Ausgabe und der Leerzeilen aus Ihrem Skript erhalten Sie das folgende bereinigte Skript:
#!/bin/bash
out=290,'02:20:00','02:40:00',20.5,NULL
echo "${out:1}"
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES ("${out:1}");" >> /tmp/crew.txt
Das Ausführen dieses SkriptsShellCheck – Shell-Skript-Analysetoolerzeugt den folgenden Fehler:
$ shellcheck myscript
Line 4:
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES ("${out:1}");" >> /tmp/crew.txt
>> ^-- SC2027: The surrounding quotes actually unquote this. Remove or escape them.
$
Das vorgeschlagene Entfernen der Anführungszeichen behebt den Fehler. Jetzt haben wir:
#!/bin/bash
out=290,'02:20:00','02:40:00',20.5,NULL
echo "${out:1}"
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (${out:1});" >> /tmp/crew.txt
Das Ausführen dieses Befehls führt jedoch immer noch nicht zur richtigen Antwort, da es echo "${out:1}"
zeigt, dass die einfachen Anführungszeichen '
nicht in gespeichert sind out
und maskiert werden müssen:
$ test.sh
90,02:20:00,02:40:00,20.5,NULL
$
Das Beheben dieses Problems führt zu:
#!/bin/bash
out=290,\'02:20:00\',\'02:40:00\',20.5,NULL
echo "${out:1}"
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (${out:1});" >> test.txt
Beachten Sie, dass ich den Ausgabedateinamen geändert habe intest.txt
Testen:
$ test.sh
90,'02:20:00','02:40:00',20.5,NULL
$ cat test.txt
INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (90,'02:20:00','02:40:00',20.5,NULL);
$
Die endgültige, korrigierte Version Ihres Skripts lautet also:
#!/bin/bash
out=290,\'02:20:00\',\'02:40:00\',20.5,NULL
echo "${out:1}"
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (${out:1});" >> >> /tmp/crew.txt
Hier endet die Lektion zum Debuggen Ihres fehlerhaften Skripts.
Antwort3
Die Lösung, die bei mir funktioniert, besteht darin, die folgende INSERT-Anweisung wiederzugeben:
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (${out:1});" >> /tmp/crew.txt
Kein Entkommen nötig. Bin mir jedoch nicht sicher, warum.