2015-04-05 71 views
3

我正在寻找一种可以快速转义字符串的工具。这项任务非常有用,但我找不到它。bash - 快速转义字符串

比方说一个例子:

hisrmline 'h | g -E "^ [0-9]* exit$"' 

如果我想手动逃避它,这是可以做到:

'hisrmline '\''h | g -E "^ [0-9]* exit$"'\''' 

但它的耗时和效率不高。所以我发现的printf%Q

[[email protected] note]$ printf "%q" hisrmline 'h | g -E "^ [0-9]* exit$"' 
hisrmlineh\ \|\ g\ -E\ \"\^\ \[0-9\]\*\ \ exit\$\"[[email protected] note]$ 
[[email protected] note]$ 

输出是错误的,因为hisrmlineh是concate一起,所以我缩小字符串:

[[email protected] note]$ printf "%q" hisrmline 'h' 
hisrmlineh[[email protected] note]$ 
[[email protected] note]$ 

我想要的是什么hisrmline \'h \'

这对grep特别有用:

[[email protected] note]$ HISTTIMEFORMAT=""; history|grep -a --color=auto hisrmline\ \'h 
7856 hisrmline 'hisrmline' 
7857 hisrmline 'hisrmline' 
7882 hisrmline 'h | g -E "^ [0-9]* exit[ ]*$"' 
7883 hisrmline 'h | g -E "^ [0-9]* exit[ ]*$"' 
7884 hisrmline 'h | g -E "' 
7885 hisrmline 'h | g ' 
7886 hisrmline 'h | g' 
7887 hisrmline 'h |' 
7890 hisrmline 'h | g -E "^ [0-9]* exit$"' 
7891 hisrmline 'h | g -E "^ [0-9]* exit$"' 
7905 h|g 'hisrmline 'h | g -E "^ [0-9]* exit$"'' 

和grep -F不会让我的生活更轻松,当处理嵌套的单引号,我仍然需要手工逃脱单引号“\”':

[[email protected] note]$ HISTTIMEFORMAT=""; history|grep -a --color=auto -F '[0-9]* exit$"'\''' 
7889 h|g -aF 'h | g -E "^ [0-9]* exit$"' 
7890 hisrmline 'h | g -E "^ [0-9]* exit$"' 
7891 hisrmline 'h | g -E "^ [0-9]* exit$"' 
7905 h|g 'hisrmline 'h | g -E "^ [0-9]* exit$"'' 
7911 h|g 'hisrmline 'h | g -E "^ [0-9]* exit$"'' 
7912 h|g 'hisrmline '"'"'h | g -E "^ [0-9]* exit$"'"'"' 

有没有更简单的方法或任何现有的实用程序来逃避任何字符串的列表?

回答

1

如果您引用命令行正常,然后printf应该工作如:

printf "%q\n" "hisrmline 'h'" 
hisrmline\ \'h\' 

或者:

printf "%q\n" "hisrmline 'h | g -E \"^ [0-9]* exit$\"'" 
hisrmline\ \'h\ \|\ g\ -E\ \"\^\ \[0-9\]\*\ \ exit\$\"\' 

编辑:你可能寻找这种逃逸:

IFS= read -r str<<"EOF" 
hisrmline 'h | g -E "^ [0-9]* exit$"' 
EOF 

printf "%q\n" "$str" 
hisrmline\ \'h\ \|\ g\ -E\ \"\^\ \[0-9\]\*\ \ exit\$\"\' 

[按更新@林果皞]

对谁可能会感兴趣,EOF必须报之以防止扩大,通过@bize如指出:

EOF无报价:

[[email protected] Downloads]$ IFS= read -r str<<EOF 
> target='h | g -E -i -e "^[ ]+[0-9]+ .*[|&; ]+g[ ]" -e "^[ ]+[0-9]+ .*[|&; ]+g$"'; history|grep -aF "$target"; echo ${#target} 
> EOF 
[[email protected] Downloads]$ printf "%q\n" "$str" 
target=\'h\ \|\ g\ -E\ -i\ -e\ \"\^\[\ \]+\[0-9\]+\ \ .\*\[\|\&\;\ \]+g\[\ \]\"\ -e\ \"\^\[\ \]+\[0-9\]+\ \ .\*\[\|\&\;\ \]+g\$\"\'\;\ history\|grep\ -aF\ \"h\ \|\ g\ -E\ -i\ -e\ \"\^\[\ \]+\[0-9\]+\ \ .\*\[\|\&\;\ \]+g\[\ \]\"\ -e\ \"\^\[\ \]+\[0-9\]+\ \ .\*\[\|\&\;\ \]+g\$\"\"\;\ echo\ 73 
[[email protected] Downloads]$ 

“EOF”援引:

[[email protected] Downloads]$ IFS= read -r str<<"EOF" 
> target='h | g -E -i -e "^[ ]+[0-9]+ .*[|&; ]+g[ ]" -e "^[ ]+[0-9]+ .*[|&; ]+g$"'; history|grep -aF "$target"; echo ${#target} 
> EOF 
[[email protected] Downloads]$ printf "%q\n" "$str" 
target=\'h\ \|\ g\ -E\ -i\ -e\ \"\^\[\ \]+\[0-9\]+\ \ .\*\[\|\&\;\ \]+g\[\ \]\"\ -e\ \"\^\[\ \]+\[0-9\]+\ \ .\*\[\|\&\;\ \]+g\$\"\'\;\ history\|grep\ -aF\ \"\$target\"\;\ echo\ \$\{#target\} 
[[email protected] Downloads]$ 

从引用输出提供,只有在正确的行为“EOF”:

[[email protected] Downloads]$ h|g -F target=\'h\ \|\ g\ -E\ -i\ -e\ \"\^\[\ \]+\[0-9\]+\ \ .\*\[\|\&\;\ \]+g\[\ \]\"\ -e\ \"\^\[\ \]+\[0-9\]+\ \ .\*\[\|\&\;\ \]+g\$\"\'\;\ history\|grep\ -aF\ \"\$target\"\;\ echo\ \$\{#target\} 
7721 target='h | g -E -i -e "^[ ]+[0-9]+ .*[|&; ]+g[ ]" -e "^[ ]+[0-9]+ .*[|&; ]+g$"'; history|grep -aF "$target"; echo ${#target} 
7725 target='h | g -E -i -e "^[ ]+[0-9]+ .*[|&; ]+g[ ]" -e "^[ ]+[0-9]+ .*[|&; ]+g$"'; history|grep -aF "$target"; echo ${#target} 
7726 atarget='h | g -E -i -e "^[ ]+[0-9]+ .*[|&; ]+g[ ]" -e "^[ ]+[0-9]+ .*[|&; ]+g$"'; history|grep -aF "$target"; echo ${#target} 
8297 target='h | g -E -i -e "^[ ]+[0-9]+ .*[|&; ]+g[ ]" -e "^[ ]+[0-9]+ .*[|&; ]+g$"'; history|grep -aF "$target"; echo ${#target} 
8320 target='h | g -E -i -e "^[ ]+[0-9]+ .*[|&; ]+g[ ]" -e "^[ ]+[0-9]+ .*[|&; ]+g$"'; history|grep -aF "$target"; echo ${#target} 

* H化名为export HISTTIMEFORMAT=""; history *g is aliased to grep的-a --color =自动

直接使用$ h|g -F "$str"是工作压力太大。

在处理unicode时,我必须在查询(history,ls..etc)源字符串之前分配LC_ALL =为空(即LC_ALL =“en_US.utf8”)。然后我必须将其切换到LC_ALL = C以使printf%q正常工作。

+0

感谢您的回答,但我的问题是寻找一种更简单/快速/更快的方式,而无需导航字符串并手动添加\“我很惊讶,因为我甚至找不到这种类型只需复制字符串并粘贴即可将其转换,而不必手动添加斜线\以便每次出现双引号“ – 2015-04-05 12:53:43

+0

否,您不必通过'\”将每个''''转义出来'手动,看到我更新的答案。你可以在变量'str'中读取整个字符串,然后简单地使用:'printf'%q \ n“”$ str“' – anubhava 2015-04-05 13:13:30

1

更新:

在您告诉您复制从历史上的线路并想重新插入一个shell命令的意见。在bashhistory expansion访问历史的一部分或修改它。可能这已经是你想要的了。

否则,你可以创建一个小的命令来显示历史转义:

IFS=$'\n' history | while read line ; do printf "%q\n" "$line"; done 

您可以从输出复制线,将其插入到一个shell字符串。如果您的$HISTSIZE较大,您可以额外输入此值。

如果需要此命令更多的时候,你可能会在.bashrc


原来的答复创建一个脚本文件出来,或创建一个功能

比方说,要使用的'为在字符串分隔符处,可以使用以下bash表达式:

string="hisrmline 'h | g -E \"^ [0-9]* exit$\"'" 
echo "${string//\'/\\\'}" 

现在你可以在bash中使用字符串。如果您想在grep或其他使用正则表达式的程序中使用它,则需要转义更多字符。但是grep支持选项-F。如果传递它,模式将作为固定字符串处理,而不是作为正则表达式处理。

+0

我知道grep -F,但是我的问题看起来更简单/快速/必须导航字符串并手动添加''''''或'\''。我正在寻找'printf%q list_of_strings',但正如你在我的问题上看到的,它在处理单引号时不起作用。 – 2015-04-05 12:33:45

+0

弦从哪里来? – hek2mgl 2015-04-05 12:37:13

+0

我的情况,它来自我的历史 – 2015-04-05 12:37:42

1

接吻的形式给出:

printf "%q" "$(cat <<"_up_to_here_" 
hisrmline 'h | g -E "^ [0-9]* exit$"' 
_up_to_here_ 
)" 

任何悫"_up_to_here_"_up_to_here_将被正确引用。

请注意: 引用第一个_up_to_here_以防止在下一行或行(S)中扩展任何$变量。

评论:使用cat是为了保持命令简单,任何企图正确转换为read将需要广泛的知识:不是KISS aproach。

+0

非常感谢您,“引用以防扩展”像@anubhava答案的同伴一样重要,EOF应该被引用。不过,我只能接受一个答案:)对于处理unicode时可能感兴趣的人,我必须在查询(history,ls..etc)源字符串之前分配LC_ALL =以清空。然后我必须将其切换到LC_ALL = C以使printf%q正常工作。 – 2015-04-06 06:43:51