
У меня есть скрипт bash, который проверяет записи в таблице. Окончательное выходное значение — $out, которое вставляется в оператор SQL INSERT, который затем добавляется в /tmp/crew.txt. Хотя $out явно разделен запятыми, между значениями в результирующем операторе INSERT в /tmp/crew.txt запятых нет. Почему так происходит и как это можно исправить, чтобы у меня были разделенные запятыми значения в /tmp/crew.txt?
#!/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);
Таким образом, результат в /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);
решение1
Гипотеза: ваша IFS
переменная содержит ,
. Скрипт не изменяет IFS
, поэтому нестандартное значение должно было быть в среде.
Этот другой ответзаметил, что вы раскрыли кавычки ${out:1}
в строке, которая выглядит так:
echo "foo"${out:1}"bar"
Переменная без кавычекпроходит разделение слов и генерацию имени файла. Разделение слов выполняется с помощью IFS
. Не заключенное в кавычки слово ${out:1}
разделяется на несколько слов, echo
получает несколько аргументов и выводит их, разделяя одинарными пробелами (потому что именно это и echo
происходит, независимо от IFS
).
Если вы использовалиprintf
как советовали, было бы проще определить, заключена ли переменная в кавычки:
printf 'INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (%s);\n' "${out:1}"
И если бы вы не заключили переменную в двойные кавычки, printf
то получили бы несколько аргументов ${out:1}
и сгенерировали бы несколько строк. Тогда должно быть совершенно очевидно, что происходит некоторое разделение. Использование, echo
которое объединяет свои аргументы, в некоторой степени запутало этот факт.
Отдельные вопросы:
Желаемый вывод предполагает, что вам не нужно,
"${out:1}"
но" $out"
с начальным пробелом.Чтобы включить одинарные кавычки в переменную, вы должны убедиться, что оболочка не удаляет их. Экранируйте их (благодарностьуже упомянутый ответ) или заключите их в двойные кавычки:
out="290,'02:20:00','02:40:00',20.5,NULL"
решение2
Почему это так и как это можно исправить?
Удаление отраженного вывода и пустых строк из вашего скрипта дает следующий очищенный скрипт:
#!/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
Хотя запуск этого скриптаShellCheck – инструмент анализа скриптов оболочкивыдает следующую ошибку:
$ 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.
$
Удаление кавычек, как предлагается, исправляет эту ошибку, и теперь у нас есть:
#!/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
Однако запуск этого кода все еще не дает правильного ответа, поскольку echo "${out:1}"
показывает, что одинарные кавычки '
не хранятся в out
, и их необходимо экранировать:
$ test.sh
90,02:20:00,02:40:00,20.5,NULL
$
Исправление этого дает:
#!/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
Обратите внимание, что я изменил имя выходного файла наtest.txt
Тестирование:
$ 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);
$
Итак, окончательная исправленная версия вашего скрипта выглядит так:
#!/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
На этом урок по отладке вашего сломанного скрипта заканчивается.
решение3
Решение, которое работает для меня, — повторить следующий оператор INSERT:
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (${out:1});" >> /tmp/crew.txt
Нет необходимости в побеге. Однако не уверен, почему.