我有一个字符串列表,我想在单个Bash命令行调用中将这些字符串作为参数传递.对于简单的字母数字字符串,只需逐字传递即可:
> script.pl foo bar baz yes no
foo
bar
baz
yes
no
Run Code Online (Sandbox Code Playgroud)
我理解如果一个参数包含空格或反斜杠或双引号,我需要反斜杠 - 转义双引号和反斜杠,然后双引号参数.
> script.pl foo bar baz "\"yes\"\\\"no\""
foo
bar
baz
"yes"\"no"
Run Code Online (Sandbox Code Playgroud)
但是当参数包含感叹号时,会发生以下情况:
> script.pl !foo
-bash: !foo: event not found
Run Code Online (Sandbox Code Playgroud)
双引号不起作用:
> script.pl "!foo"
-bash: !foo: event not found
Run Code Online (Sandbox Code Playgroud)
反斜杠也不会逃避(注意输出中的字面反斜杠如何):
> script.pl "\!foo"
\!foo
Run Code Online (Sandbox Code Playgroud)
我对Bash了解不多,但我知道还有其他特殊字符可以做类似的事情.在Bash中安全地转义任意字符串以用作命令行参数的一般过程是什么?假设字符串可以是任意长度并包含特殊字符的任意组合.我想要一个escape()
子程序,我可以使用如下(Perl示例):
$cmd = join " ", map { escape($_); } @args;
Run Code Online (Sandbox Code Playgroud)
下面是一些应该通过此函数安全转义的示例字符串(我知道其中一些看起来像Windows,这是故意的):
yes
no
Hello, world [string with a comma and space in it]
C:\Program Files\ [path with backslashes and a space in it]
" [i.e. a double-quote]
\ [backslash]
\\ [two backslashes]
\\\ [three backslashes]
\\\\ [four backslashes]
\\\\\ [five backslashes]
"\ [double-quote, backslash]
"\T [double-quote, backslash, T]
"\\T [double-quote, backslash, backslash, T]
!1
!A
"!\/'" [double-quote, exclamation, backslash, forward slash, apostrophe, double quote]
"Jeff's!" [double-quote, J, e, f, f, apostrophe, s, exclamation, double quote]
$PATH
%PATH%
&
<>|&^
*@$$A$@#?-_
Run Code Online (Sandbox Code Playgroud)
编辑:
这会诀窍吗?使用反斜杠逃避每个不寻常的角色,并省略单引号或双引号.(例子是在Perl中,但任何语言都可以这样做)
sub escape {
$_[0] =~ s/([^a-zA-Z0-9_])/\\$1/g;
return $_[0];
}
Run Code Online (Sandbox Code Playgroud)
l0b*_*0b0 19
如果你想为Bash 安全地引用任何内容,你可以使用它的内置printf %q
格式:
cat strings.txt
:
yes
no
Hello, world
C:\Program Files\
"
\
\\
\\\
\\\\
\\\\\
"\
"\T
"\\T
!1
!A
"!\/'"
"Jeff's!"
$PATH
%PATH%
&
<>|&^
*@$$A$@#?-_
Run Code Online (Sandbox Code Playgroud)
cat quote.sh
:
#!/bin/bash
while IFS= read -r -d $'\n'
do
printf %q "$REPLY"
printf '\n'
done < strings.txt
Run Code Online (Sandbox Code Playgroud)
./quote.sh
:
yes
no
Hello\,\ world
C:\\Program\ Files\\
\"
\\
\\\\
\\\\\\
\\\\\\\\
\\\\\\\\\\
\"\\
\"\\T
\"\\\\T
\!1
\!A
\"\!\\/\'\"
\"Jeff\'s\!\"
\$PATH
%PATH%
\&
\<\>\|\&\^
\*@\$\$A\$@#\?-_
Run Code Online (Sandbox Code Playgroud)
可以逐字复制这些字符串,例如echo
在strings.txt中输出原始字符串.
Tan*_*ett 11
在Bash中安全地转义任意字符串以用作命令行参数的一般过程是什么?
更换的每次出现'
用'\''
,然后把'
在开头和结尾.
除单引号外的每个字符都可以在单引号分隔的字符串中逐字使用.没有办法在单引号分隔的字符串中放入单引号,但这很容易解决:结束字符串('
),然后使用反斜杠添加单引号以逃避它(\'
),然后开始一个新的string('
).
据我所知,这将永远有效,没有例外.
Bash 仅在交互模式下解释感叹号。
您可以通过执行以下操作来防止这种情况:
set +o histexpand
Run Code Online (Sandbox Code Playgroud)
在双引号内,您必须转义美元符号、双引号、反斜杠,我想说仅此而已。