我正在寻找能够快速逃脱一串字符的实用程序。这项任务非常有用,但我找不到它。
让我们举一个例子:
hisrmline 'h | g -E "^ [0-9]* exit$"'
如果我想手动转义它,可以这样做:
'hisrmline '\''h | g -E "^ [0-9]* exit$"'\'''
但这耗费时间并且效率不高。所以我发现 printf%q :
[xiaobai@xiaobai note]$ printf "%q" hisrmline 'h | g -E "^ [0-9]* exit$"'
hisrmlineh\ \|\ g\ -E\ \"\^\ \[0-9\]\*\ \ exit\$\"[xiaobai@xiaobai note]$
[xiaobai@xiaobai note]$
输出错误,因为hisrmlineh连在一起,所以我缩小了字符串:
[xiaobai@xiaobai note]$ printf "%q" hisrmline 'h'
hisrmlineh[xiaobai@xiaobai note]$
[xiaobai@xiaobai note]$
我想要的是 hisrmline \ \'h'
这对grep:
特别有用[xiaobai@xiaobai 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在处理嵌套单引号时不会让我的生活更轻松,我仍然需要手动转义单引号'\'':
[xiaobai@xiaobai 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$"'"'"'
是否有更简单的方法或任何现有的实用程序来转义任何字符串的列表?
答案 0 :(得分: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\$\"\'
[@林果UP更新]
对于可能感兴趣的人,EOF必须引用以防止扩张,如@bize所述:
没有引用的EOF:
[xiaobai@xiaobai 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
[xiaobai@xiaobai 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
[xiaobai@xiaobai Downloads]$
引用“EOF”:
[xiaobai@xiaobai 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
[xiaobai@xiaobai Downloads]$ printf "%q\n" "$str"
target=\'h\ \|\ g\ -E\ -i\ -e\ \"\^\[\ \]+\[0-9\]+\ \ .\*\[\|\&\;\ \]+g\[\ \]\"\ -e\ \"\^\[\ \]+\[0-9\]+\ \ .\*\[\|\&\;\ \]+g\$\"\'\;\ history\|grep\ -aF\ \"\$target\"\;\ echo\ \$\{#target\}
[xiaobai@xiaobai Downloads]$
仅在引用的“EOF”输出中提供正确的行为:
[xiaobai@xiaobai 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 = auto
直接使用$ h|g -F "$str"
也有效。
当处理unicode时,我必须在查询(history,ls..etc)源字符串之前将LC_ALL =指定为空(即LC_ALL =“en_US.utf8”)。然后我必须将其切换到LC_ALL = C以使printf%q正常工作。
答案 1 :(得分:1)
<强>更新强>
在评论中,您告诉您复制历史记录中的行并希望将它们重新插入shell命令中。在bash
中,history 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
。如果你传递它,模式将被处理为固定字符串,而不是正则表达式。
答案 2 :(得分: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方法。