我在bash脚本中有一个我不理解的奇怪行为。
基本上在下面的代码中我尝试转义元字符......
while IFS=, read _type _content; do
if [ -z "$patternfilter" ]; then
if [ "$_type" == "rex" ]; then
patternfilter="$_content"
elif [ "$_type" == "txt" ]; then
patternfilter="`echo "$_content" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g'`"
fi
else
if [ "$_type" == "rex" ]; then
patternfilter="$patternfilter|$_content"
elif [ "$_type" == "txt" ]; then
patternfilter="$patternfilter|`echo "$_content" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g'`"
fi
fi
done < $patternfile
输出口给我以下内容:
blabal \ 1bla \ 1blabla \ 1toto \ 1COM
而不是:
blabal \(BLA \)布拉布拉\ [TOTO \] \。com
如果我直接在控制台中输入它运作的代码......我会想念一些东西,但我不知道是什么。
[root]# patternfilter="blabal(bla)blabla[toto].com"
[root]# echo "$patternfilter" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g'
blabal\(bla\)blabla\[toto\]\.com
答案 0 :(得分:4)
您无法可靠地转义sed中的字符,因为字符是否需要转义是上下文相关的。此外,shell是一个可以从中调用工具的环境。用于操作文本的标准UNIX工具是awk。只需让你的shell调用awk来做所有事情。顺便说一下,使用`...`而不是$(...)
将解释双重转义,而使用不带-r
的读取将扩展转义。
SInce awk可以操作字符串以及RE几乎肯定不会逃避任何东西,因为逃避字符的通常理由是尝试使你的工具只能在RE上工作在字符串上,这是不可能的任务。
如果您告诉我们您正在尝试使用patternfilter
以及一些示例输入和预期输出,我们可以向您展示如何简单而强大地执行此操作。
答案 1 :(得分:2)
检查下一个脚本:
while IFS=, read -r line; do
result1="`echo "$line" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g'`"
echo "1=$result1="
result2="$(echo "$line" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g')"
echo "2=$result2="
done <<'EOF'
blabal(bla)blabla[toto].com
EOF
打印:
1=blabal\1bla\1blabla\1toto]\1com=
2=blabal\(bla\)blabla\[toto\]\.com=
反引号的instad使用$()
,与result2=...
行一样。 (并始终使用-r
作为read -r
)
使用printf "%q"
这样的
while IFS=, read _type _content; do
res=$(printf "%q" "$_content")
echo "==$res=="
done <<EOF
txt,blabal(bla)blabla[toto].com
EOF
打印什么
==blabal\(bla\)blabla\[toto\].com==
但是,请阅读@ EdMorton的回答。