我有一个脚本,该脚本读取文本流并生成sed命令文件,该文件随后与一起运行sed -f
。生成的sed命令类似于:
s/cid:image002\.gif@01CC3D46\.926E77E0/https:\/\/mysite.com\/files\/1922/g
s/cid:image003\.gif@01CC3D46\.926E77E0/https:\/\/mysite.com\/files\/1923/g
s/cid:image004\.jpg@01CC3D46\.926E77E0/https:\/\/mysite.com\/files\/1924/g
假设生成sed
命令的脚本类似于:
while read cid fileid
do
cidpat="$(echo $cid | sed -e s/\\./\\\\./g)"
echo 's/'"$cidpat"'/https:\/\/mysite.com\/files\/'"$fileid"'/g' >> sedscr
done
如何改善脚本以确保cid
字符串中的所有正则表达式元字符均已转义并正确插值?
为了逃避变量上的左侧和右侧可以使用s
命令sed
(这里$lhs
和$rhs
分别),你会怎么做:
escaped_lhs=$(printf '%s\n' "$lhs" | sed 's:[][\\/.^$*]:\\&:g')
escaped_rhs=$(printf '%s\n' "$rhs" | sed 's:[\\/&]:\\&:g;$!s/$/\\/')
sed "s/$escaped_lhs/$escaped_rhs/"
请注意,$lhs
不能包含换行符。
也就是说,在LHS上,转义所有正则表达式运算符(][.^$*
),转义字符本身(\
)和分隔符(/
)。
在RHS上,您只需要转义&
,分隔符,反斜杠和换行符(可通过在每行的末尾插入反斜杠(最后一行($!s/$/\\/
)除外)来完成此操作)。
这假设你用/
在你的分隔符sed
s
的命令和你没有启用扩展的RE与-r
(GNU sed
/ ssed
/ ast
/ busybox sed
)或-E
(BSD系统,ast
最近GNU,最近busybox的)或PCREs用-R
(ssed
)或增强的RE与-A
/ -X
(ast
),它都有额外的RE运算符。
处理任意数据时的一些基本规则:
echo
sed
命令在与该sed
命令相同的语言环境中运行很重要)sed
$lhs
包含换行符并采取措施)。另一种选择是在环境中使用perl
代替sed
并传递字符串,并使用\Q
/ \E
perl
regexp运算符从字面上接受字符串:
A="$lhs" B="$rhs" perl -pe 's/\Q$ENV{A}\E/$ENV{B}/g'
perl
(默认情况下)不受语言环境字符集的影响,因为在上面,它仅将字符串视为字节数组,而无需关心它们可以为用户代表什么字符(如果有)。使用sed
,您可以通过将所有命令的语言环境固定为C
withLC_ALL=C
来实现相同的目的sed
(尽管这也会影响错误消息的语言,如果有的话)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句