构建包含用单引号括起来的变量值的bash字符串

时间:2012-11-28 14:24:31

标签: string bash variables quote

我正在做一个应该是最微不足道的任务的噩梦。

我的最终目标是从bash脚本发出以下命令:
sqlite3 my_db.db '.read my_file.sql'

这里有两个捕获:
1.单引号是强制性的,不能用双引号替换 2. my_file.sql是仅在运行时才知道的变量。

所以我需要的是一种让bash构建一个字符串的方法,一方面包含一个变量值,另一方面该值应该用单引号括起来。

我也更喜欢不依赖AWK,Perl等其他工具的解决方案。如果真的有必要,也许是sed。

感谢。


感谢Jonathan和Nelson。

我尝试了所有三个建议,但都失败了 为简单起见,我将问题简化为以下内容:

  1. 我写了以下脚本(tst.sh):
    #!/bin/bash
    file=/tmp/1
    ls "'"$file"'"
    ls \'$file\'
    ls "'$file'"

  2. 然后我提出以下命令:
    $ touch /tmp/1
    $ ls '/tmp/1'
    /tmp/1
    $ ./tst.sh
    '/tmp/1': No such file or directory
    '/tmp/1': No such file or directory
    '/tmp/1': No such file or directory

  3. 似乎确实添加了引号,但结果命令与手动输入时的命令不同。

    有什么想法吗?

5 个答案:

答案 0 :(得分:1)

单引号必须。所有以下命令都使用完全相同的参数运行sqlite3:

sqlite3 my_db.db '.read my_file.sql'
sqlite3 my_db.db ".read my_file.sql"
sqlite3 my_db.db .read\ my_file.sql
sqlfile="my_file.sql"
sqlite3 my_db.db ".read $sqlfile"

在所有情况下,在将参数传递给sqlite3之前,引号(/ escape)将被解析并删除。这就是你想要的。您希望sqlite3获得两个参数:my_db.db.read my_file.sql。你希望sqlite3看到命令周围的引号 - 这相当于:

$ sqlite3 my_db.db
SQLite version 3.7.7 2011-06-25 16:35:41
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> '.read my_file.sql'
   ...>

......正如你所看到的,只是混淆了sqlite3。

顺便说一句,这与你的ls例子中的问题相同:你将单引号作为参数的一部分传递给ls,所以它正在查找名称中带有单引号但未找到它的文件。您希望 shell删除引号,而不是将它们作为参数的一部分传递给命令。

答案 1 :(得分:0)

您可以执行以下操作:

VAR=my_file.sql
VAR2="'.read $VAR'"
sqlite3 my_db.db $VAR2

答案 2 :(得分:0)

这将按照您的意思执行(获取程序的单引号),但它使用双引号:

sqlite3 my_db.db "'".read" "my_file.sql"'"

避免使用双引号,您可以写:

sqlite3 my_db.db \'.read\ my_file.sql\'

对于这两个,sqlite3将第二个参数视为包含以下内容的字符串:

'.read my_file.sql'

如果文件名在变量(file=my_file.sql)中,则:

sqlite3 my_db.db "'".read" "$file"'"
sqlite3 my_db.db \'.read\ $file\'

如果文件名包含空格,这些符号很容易混淆。

但是,我不认为这可能是你真正想要的。双引号的禁令令人费解,单引号的要求同样令人费解。

答案 3 :(得分:0)

user1860085,如果您查看 sqlite3 命令的文档,并且您将知道shell如何处理引号和空格,您可能会得出结论,您需要双引号用于您的情况。

但是如果你真的想要单引号,这里有解决方案:

eval sqlite3 my_db.db \'.read $VARIABLE\'
飞行中的

将变为:

sqlite3 my_db.db '.read my_file.sql'

但我不明白为什么你会想要它......

答案 4 :(得分:-2)

好的,问题解决了!!

所有缺失的是添加一点“评估”。行前命令。
因此,在我给出的简单示例脚本中,更改:
ls "'$file'"至:
eval ls "'$file'"
做了这个工作。

感谢所有回复者: - )