如何停止 bash 引用报价?

how to stop bash quoting quotes?

我想 运行 一个小的 bash 脚本,但是我在引号周围添加了额外的垃圾。 我以为使用单引号 ' 会给我一个文字字符串?

我使用 set +x 来查看脚本的实际作用。 代码是这样的:

set -x
task='mysql --port=3336 --host=127.0.0.1 -u root training_service -e "DELETE FROM expert_bundle_claim; " '
echo $task
$task

当我 运行 我会看到:

▶ bin/run-local.sh

+ task='mysql --port=3336 --host=127.0.0.1 -u root training_service -e "DELETE FROM expert_bundle_claim; " '
+ echo mysql --port=3336 --host=127.0.0.1 -u root training_service -e '"DELETE' FROM 'expert_bundle_claim;' '"'
mysql --port=3336 --host=127.0.0.1 -u root training_service -e "DELETE FROM expert_bundle_claim; "
+ mysql --port=3336 --host=127.0.0.1 -u root training_service -e '"DELETE' FROM 'expert_bundle_claim;' '"'
mysql  Ver 14.14 Distrib 5.6.47, for osx10.15 (x86_64) using  EditLine wrapper
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.


然后是错误。

所以基本上实际的 SQL 命令 "DELETE FROM expert_bundle_claim; " 被破坏为 '"DELETE' FROM 'expert_bundle_claim;' '"'

我试过把 '" inner/outer 颠倒过来,结果更乱了。

+ task='mysql --port=3336 --host=127.0.0.1 -u root training_service -e '\'' DELETE FROM expert_bundle_claim; '\'' '
+ mysql --port=3336 --host=127.0.0.1 -u root training_service -e ''\''' DELETE FROM 'expert_bundle_claim;' ''\'''

尝试了另一种方法,只是用 < filename.sql 管道进入 mysql,但它被插入到引用的 '<'

+ task='mysql --port=3336 --host=127.0.0.1 -u root training_service < ./bin/revert_tasks.sql'
+ mysql --port=3336 --host=127.0.0.1 -u root training_service '<' ./bin/revert_tasks.sql

有什么建议可以最好地处理这个问题并防止插值吗?

不要将代码存储在变量中。获得正确的报价是一场噩梦。改用函数。您可以像往常一样编写代码,而无需任何特殊的引用或转义。

task() {
    mysql --port=3336 --host=127.0.0.1 -u root training_service -e "DELETE FROM expert_bundle_claim; "
}

task

您的尝试无效的原因是 Bash 的扩展规则。当像 $task 这样的变量被扩展时,Bash 不会解析扩展产生的引号。它只查看原始命令行中的引号。扩展产生的引号被视为文字字符,就好像它们是用 \"'"'.

转义的一样

有关详细信息,请参阅: