4

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

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

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

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

我也更喜欢不依赖其他工具(如 AWK、Perl 等)的解决方案。如果真的有必要,也许可以使用 sed。

谢谢。


感谢乔纳森和尼尔森。

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

  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

似乎确实添加了引号,但生成的命令与手动输入的命令不同。

有任何想法吗 ?

4

5 回答 5

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"

在所有情况下,引号 (/escape)在参数传递给 sqlite3 之前都会被解析和删除。这就是你想要的。您希望 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 删除引号,而不是将它们作为参数的一部分传递给命令。

于 2012-11-28T16:13:21.867 回答
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\'

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

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

于 2012-11-28T14:33:00.793 回答
0

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

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

eval sqlite3 my_db.db \'.read $VARIABLE\'

在飞行中将更改为:

sqlite3 my_db.db '.read my_file.sql'

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

于 2012-11-28T16:21:33.443 回答
0

您可以执行以下操作:

VAR=my_file.sql
VAR2="'.read $VAR'"
sqlite3 my_db.db $VAR2
于 2012-11-28T14:28:28.833 回答
-2

好的,问题解决了!!

所缺少的只是在该行之前添加一个小“eval”命令。
因此,在我给出的简单示例脚本中,将:更改
ls "'$file'"为:
eval ls "'$file'"
完成了这项工作。

感谢所有回复者:-)

于 2012-11-28T16:17:06.430 回答