![当附加到其他文件时,带有逗号分隔值的 Bash 脚本变量不是以逗号分隔的](https://linux22.com/image/1627277/%E5%BD%93%E9%99%84%E5%8A%A0%E5%88%B0%E5%85%B6%E4%BB%96%E6%96%87%E4%BB%B6%E6%97%B6%EF%BC%8C%E5%B8%A6%E6%9C%89%E9%80%97%E5%8F%B7%E5%88%86%E9%9A%94%E5%80%BC%E7%9A%84%20Bash%20%E8%84%9A%E6%9C%AC%E5%8F%98%E9%87%8F%E4%B8%8D%E6%98%AF%E4%BB%A5%E9%80%97%E5%8F%B7%E5%88%86%E9%9A%94%E7%9A%84.png)
我有一个用于验证表条目的 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
无需转义。但不清楚为什么。