我的 bash 脚本中的引号有问题

我的 bash 脚本中的引号有问题

如何在这个从数据库中搜索某些内容的脚本中做到这一点。他搜索了它并在终端中更改了它的名称。我对这里的引号有问题。也许有人知道如何修复它?

spr-ustawien()
{
echo -e "\e[31;43mSprawdzanie Ustawień\e[0m \e[101mIP $1\e[0m"
intertube=0
while [ $intertube -ne 1 ]; do
ping $1 -c 5
if [ $? -eq 0 ]; then
sshpass -p (pass) ssh -t (user)@$1 "
sudo sqlite3 config.sqlite "SELECT * FROM settings" |grep "SALE_POINT" | awk '{sub(/SALE_POINT/,"\033[1mPunkt Sprzedaży:\033[0m")}1' &&
exit "
echo -e "\e[1;5;32mSprawdzony\e[0m"
intertube=1;
else
echo -e "\e[1;5;31m!!! JEST OFFLINE !!!\e[0m"
break
fi
done
}

答案1

在我看来,基本问题是引号没有按照您在ssh命令中使用它们的方式嵌套。也就是说,在此命令中:

sshpass -p (pass) ssh -t (user)@$1 "
sudo sqlite3 config.sqlite "SELECT * FROM settings" |grep "SALE_POINT" | awk '{sub(/SALE_POINT/,"\033[1mPunkt Sprzedaży:\033[0m")}1' &&
exit "

in实际上是一个闭引号(与上一行的开引号匹配),因此它不是位于两层引号内",而是实际上完全不被引用(结果,将扩展为本地目录中的文件列表,从而造成不知道是什么混乱)。"SELECT * FROM...SELECT * FROM settings*

正如 djdomi 在评论中所说,您可以通过将命令ssh替换为来查看 shell 解析参数后参数的样子(以及因此将发送到远程系统执行的内容)。当我运行这个时:sshecho

echo "
sudo sqlite3 config.sqlite "SELECT * FROM settings" |grep "SALE_POINT" | awk '{sub(/SALE_POINT/,"\033[1mPunkt Sprzedaży:\033[0m")}1' &&
exit "

它打印:

sudo sqlite3 config.sqlite SELECT file1.txt file2.jpg FROM settings |grep SALE_POINT | awk '{sub(/SALE_POINT/,033[1mPunkt Sprzedaży:033[0m)}1' &&
exit 

最直接的解决方案是转义内部双引号,这样本地 shell 就会将它们传递到远程系统上的 shell:

sshpass -p (pass) ssh -t (user)@$1 "
sudo sqlite3 config.sqlite \"SELECT * FROM settings\" |grep \"SALE_POINT\" | awk '{sub(/SALE_POINT/,\"\033[1mPunkt Sprzedaży:\033[0m\")}1' &&
exit "

注意你必须逃跑全部其中,甚至是单引号awk命令中的命令,因为那些单引号对于本地 shell 来说没有任何意义。

...但我建议稍微简化一下。我看不出有什么理由需要在远程系统而不是本地系统上运行和(并且该grep命令没有做任何有用的事情,因为它无论如何都会退出)。因此,您可以将和命令移到命令之外:awkexitgrepawkssh

sshpass -p (pass) ssh -t (user)@$1 "sudo sqlite3 config.sqlite \"SELECT * FROM settings\"" |
    grep "SALE_POINT" |
    awk '{sub(/SALE_POINT/,"\033[1mPunkt Sprzedaży:\033[0m")}1'

我总是讨厌看到grep以前使用过awk,因为awk它完全能够自己做所有事情:

sshpass -p (pass) ssh -t (user)@$1 "sudo sqlite3 config.sqlite \"SELECT * FROM settings\"" |
    awk '/SALE_POINT/ {sub(/SALE_POINT/,"\033[1mPunkt Sprzedaży:\033[0m"); print}'

我还建议用双引号引起来所有变量引用(例如,ping "$1" -c 5而不仅仅是ping $1 -c 5),并将其替换为:

ping $1 -c 5
if [ $? -eq 0 ]; then

只需:

if ping "$1" -c 5; then

最后,我建议使用printf而不是echo -e-- 它更可预测。printf使用起来有点复杂 -- 第一个参数是一个格式字符串,它告诉它如何打印任何剩余的参数,并且它不会自动在末尾添加换行符(因此使用 明确添加一个\n) -- 但它不太可能因为 shell 版本的某些更改而中断echo(就像我前段时间遇到的那样……)。因此使用例如

printf "\e[31;43m%s\e[0m \e[101m%s1\e[0m\n" "Sprawdzanie Ustawień" "IP $1"

哦,我始终建议你通过shellcheck.net——它会指出许多常见的错误和不良做法。

相关内容