比方说,你有一个Bash别名:
alias rxvt='urxvt'
这很好。
然而:
alias rxvt='urxvt -fg '#111111' -bg '#111111''
不管用,也不管用:
alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''
那么,一旦有转义引号,如何在字符串中匹配开始和结束引号呢?
alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
看起来很笨拙,但如果允许像这样连接它们,它将表示相同的字符串。
我并没有特别提到引用问题,因为,有时候,考虑另一种方法是合理的。
rxvt() { urxvt -fg "#${1:-000000}" -bg "#${2:-FFFFFF}"; }
你可以调用它为:
rxvt 123456 654321
这个想法是你现在可以在不考虑引号的情况下使用别名:
alias rxvt='rxvt 123456 654321'
或者,如果你出于某种原因需要在所有调用中包含#:
rxvt() { urxvt -fg "${1:-#000000}" -bg "${2:-#FFFFFF}"; }
你可以调用它为:
rxvt '#123456' '#654321'
那么,当然,别名是:
alias rxvt="rxvt '#123456' '#654321'"
(哦,我想我确实提到了引用:)
shell_escape () {
printf '%s' "'${1//\'/\'\\\'\'}'"
}
实现说明:
双引号,这样我们可以很容易地输出换行单引号,并使用${…}语法
Bash的搜索和替换如下:${varname//search/replacement}
我们用“\”代替“\”
'\ "编码单个',如下所示:
单引号结束
\'编码a '(需要反斜杠,因为我们不在引号内)
又开始了单引号
Bash自动连接字符串,中间没有空格
在每个\和`之前都有一个\,因为这是${…//…/…的转义规则。}。
string="That's "'#@$*&^`(@#'
echo "original: $string"
echo "encoded: $(shell_escape "$string")"
echo "expanded: $(bash -c "echo $(shell_escape "$string")")"
注:始终编码为单引号字符串,因为它们比双引号字符串简单得多。
这是另一个解决方案。这个函数将接受一个参数,并使用单引号字符适当地引用它,就像上面被投票的答案解释的那样:
single_quote() {
local quoted="'"
local i=0
while [ $i -lt ${#1} ]; do
local ch="${1:i:1}"
if [[ "$ch" != "'" ]]; then
quoted="$quoted$ch"
else
local single_quotes="'"
local j=1
while [ $j -lt ${#1} ] && [[ "${1:i+j:1}" == "'" ]]; do
single_quotes="$single_quotes'"
((j++))
done
quoted="$quoted'\"$single_quotes\"'"
((i+=j-1))
fi
((i++))
done
echo "$quoted'"
}
所以,你可以这样用:
single_quote "1 2 '3'"
'1 2 '"'"'3'"'"''
x="this text is quoted: 'hello'"
eval "echo $(single_quote "$x")"
this text is quoted: 'hello'
我总是将每个嵌入的单引号替换为序列:'\ "(即:quote反斜杠quote quote),它关闭字符串,附加一个转义的单引号并重新打开字符串。
我经常在Perl脚本中创建一个“quotify”函数来为我做这件事。步骤如下:
s/'/'\\''/g # Handle each embedded quote
$_ = qq['$_']; # Surround result with single quotes.
这基本上解决了所有情况。
当您在shell脚本中引入eval时,生活会变得更加有趣。你必须重新对所有东西进行报价!
例如,创建一个名为quotify的Perl脚本,包含上面的语句:
#!/usr/bin/perl -pl
s/'/'\\''/g;
$_ = qq['$_'];
然后使用它生成一个正确引用的字符串:
$ quotify
urxvt -fg '#111111' -bg '#111111'
结果:
'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
然后可以复制/粘贴到alias命令:
alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
(如果需要在eval中插入该命令,请再次运行quotify:
$ quotify
alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
结果:
'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''
可以复制/粘贴到eval中:
eval 'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''