2012-11-28 86 views
4

我从最应该做的最琐碎的任务中做了一场噩梦。构建包含单引号的变量值的bash字符串

我的最终目标是从一个bash脚本发出以下命令:
​​

有两个锁扣位置:
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

这似乎是确实增加了报价,但由此产生的命令是不一样的手动输入时。

任何想法?

+3

单引号是强制性的原因是什么?这应该是单引号或两个参数中的一个参数,一个以单引号开头,另一个以单引号结尾。 –

回答

0

你可以做如下:

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

或者没有变量'sqlite3 my_db.db“'.read my_file.sql'”'但我怀疑这实际上是解决方案,尽管这就是OP所要求的。 – tripleee

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\' 

这些标记,易受混淆。

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

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之前删除。这是你想要的。你想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删除引号,而不是将它们作为参数的一部分传递给命令。

+0

谢谢戈登 - 这是我不知道的重要信息。我的问题虽然比sqlite3语法更广泛,但在主题中可以看到。我相信我的最后一个答案在许多其他情况下会对其他人有所帮助。 – Ash

+1

@ user1860085:深吸一口气,了解这里几位评论者反复试图解释的内容:您正在解决错误的问题,并且您需要了解shell的引用机制。 – tripleee

+0

并为这个清晰的答案+1。 – tripleee

-2

好的,问题解决了!

所有缺少的是在该行之前添加一个“eval”命令。
因此,在简单的示例脚本我放弃,改:
ls "'$file'"到:
eval ls "'$file'"
做的工作。

感谢:-)

+0

啊,不! eval的主要目的是创建不可理解的错误。如果您确切地知道*您正在做什么,它可以安全地使用,但这不是其中的一种情况。 –

+0

它显示了如何摆脱两层引号,但最终结果完全等价于'ls“$ file”'。 – tripleee

+0

大声笑,对不起,没有进攻意图;-)你可以详细说明你提到的eval的问题性质,以及它会如何危及我的解决方案(这似乎是工作..)? – Ash

0

user1860085所有replyers,如果你看看文档sqlite3的命令,你就会知道如何shell对引号和空格,你可能会来,你要双引号结束为你的情况。

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

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

这在飞将变更为:

sqlite3 my_db.db '.read my_file.sql' 

但我不明白为什么你能想到它。 ..

相关问题