我似乎陷入了矛盾的境地.我有一个长字符串存储在一个变量中,$abstract如下所示:
abstract='test1 and "test2"'
Run Code Online (Sandbox Code Playgroud)
你看到字符串中有一个引号,我想把这个字符串作为一个参数发送到一个命令,我尝试了以下命令:
command_name "$abstract"
Run Code Online (Sandbox Code Playgroud)
在变量替换之后,它变成:command_name test1 and "test2".如果我尝试:
command_name \"$abstract\"
Run Code Online (Sandbox Code Playgroud)
它变成:command_name "test1 and "test2"".两者都不是我想要的.谁能告诉我如何实现我的目标?
你的第一次尝试是正确的:
command_name "$abstract"
Run Code Online (Sandbox Code Playgroud)
command_name用一个参数执行,test1 and "test2".例如:
:; mkdir empty
:; cd empty
:; abstract='test1 and "test2"'
:; touch "$abstract"
:; ls -l
total 0
-rw-r--r-- 1 mayoff wheel 0 Mar 2 21:26 test1 and "test2"
Run Code Online (Sandbox Code Playgroud)
您可以看到touch只创建了一个文件,并且它已命名test1 and "test2".
因此,根据您的注释,您实际上希望将shell变量插入到SQL语句中以将命令行传递给sqlite3.
首先,您应该知道"在SQLite3中引用字符串是危险的.它允许作为常规规则的例外,如"SQLite关键字"文档中所述,该文档还说"SQLite的未来版本可能会更改以引发错误,而不是接受上述异常所涵盖的格式错误的语句."
所以,如果我们按照预期使用单引号,你想执行这个:
sqlite3 test.db "insert into test values('$abstract')"
Run Code Online (Sandbox Code Playgroud)
当然,这适用于您给出的示例值$abstract.
让我们改为更具挑战性的版本$abstract:
abstract="'test' and \"test2\""
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,我们需要在SQLite看到之前引用单引号.在SQLite3字符串中,一行中的两个单引号表示一个单引号.也就是说,我们想运行这个SQLite3命令:
insert into test values('''test'' and "test2"')
Run Code Online (Sandbox Code Playgroud)
无论如何,bash实际上有一个方便的方法.在bash,你可以说${variable//PATTERN/STRING},和bash将扩大,为的值$variable,但它将替换的每个实例都PATTERN与STRING在扩张.我们可以用它来$abstract用两个单引号替换每个单引号.但是单引号在出现时是狂妄的PATTERN,所以我们必须用反斜杠引用那里的单引号.但是我们没有引用替换中的单引号STRING.哇,这让人感到困惑,不是吗?
无论如何,你正在寻找的神奇咒语是这样的:
sqlite3 test.db "insert into test values('${abstract//\'/''}')"
Run Code Online (Sandbox Code Playgroud)
我们可以用touch以下方法测试:
:; mkdir empty
:; cd empty
:; touch sqlite3 test.db "insert into test values('${abstract//\'/''}')"
:; ls -l
total 0
-rw-r--r-- 1 mayoff wheel 0 Mar 3 15:01 insert into test values('''test'' and "test2"')
-rw-r--r-- 1 mayoff wheel 0 Mar 3 15:01 sqlite3
-rw-r--r-- 1 mayoff wheel 0 Mar 3 15:01 test.db
Run Code Online (Sandbox Code Playgroud)
或者我们当然可以用SQLite测试它:
:; rm -f test.db
:; sqlite3 test.db 'create table test (x)'
:; sqlite3 test.db "insert into test values('${abstract//\'/''}')"
:; sqlite3 test.db 'select * from test'
'test' and "test2"
Run Code Online (Sandbox Code Playgroud)