Переменная скрипта Bash со значениями, разделенными запятыми, не разделяется запятыми при добавлении в другой файл

Переменная скрипта Bash со значениями, разделенными запятыми, не разделяется запятыми при добавлении в другой файл

У меня есть скрипт 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

Нет необходимости в побеге. Однако не уверен, почему.

Связанный контент