当附加到其他文件时,带有逗号分隔值的 Bash 脚本变量不是以逗号分隔的

当附加到其他文件时,带有逗号分隔值的 Bash 脚本变量不是以逗号分隔的

我有一个用于验证表条目的 bash 脚本。最终输出值是 $out,它被插入到 SQL INSERT 语句中,然后附加到 /tmp/crew.txt。虽然 $out 显然是用逗号分隔的,但 /tmp/crew.txt 中生成的 INSERT 语句中的值之间没有逗号。为什么会出现这种情况?如何修复它,以便我在 /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"带有前导空格。

  • 要在变量中包含单引号,您应该确保 shell 不会删除它们。将它们转义(归功于已经提到答案)或者用双引号括起来:

    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 – shell脚本分析工具产生以下错误:

$ 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

无需转义。但不清楚为什么。

相关内容