Regex 使用用户指定的替换字符串进行sed替换

Regex 使用用户指定的替换字符串进行sed替换,regex,linux,bash,sed,Regex,Linux,Bash,Sed,in的一般形式为: 其中,“/”字符可以统一替换为任何其他单个字符。但是,当替换字符串由环境变量输入并且可能包含任何可打印字符时,如何选择此分隔符?使用bash是否有一种直接的方法来转义变量中的分隔符 这些值来自受信任的管理员,因此安全性不是我主要关心的问题。(换句话说,请不要回答“永远不要这样做!”)不过,我无法预测替换字符串中需要显示哪些字符。您可以使用控制字符作为正则表达式分隔符,也可以这样: s^Aregexp^Areplacement^Ag 其中,^A是CTRLva压在一起的 或者使

in的一般形式为:

其中,“/”字符可以统一替换为任何其他单个字符。但是,当替换字符串由环境变量输入并且可能包含任何可打印字符时,如何选择此分隔符?使用
bash
是否有一种直接的方法来转义变量中的分隔符


这些值来自受信任的管理员,因此安全性不是我主要关心的问题。(换句话说,请不要回答“永远不要这样做!”)不过,我无法预测替换字符串中需要显示哪些字符。

您可以使用控制字符作为正则表达式分隔符,也可以这样:

s^Aregexp^Areplacement^Ag
其中,
^A
是CTRLva压在一起的

或者使用
awk
,不用担心分隔符:

awk -v s="search" -v r="replacement" '{gsub(s, r)} 1' file
使用
sed
解决以下问题并不容易

while read -r string from to wanted
do
    echo "in [$string] want replace [$from] to [$to]  wanted result: [$wanted]"
    final=$(echo "$string" | sed "s/$from/$to/")
    [[ "$final" == "$wanted" ]] && echo OK || echo WRONG
    echo
done <<EOF
=xxx= xxx === =====
=abc= abc /// =///=
=///= /// abc =abc=
EOF
无法抗拒:永远不要这样做!(附sed.:)

是否有一种简单的方法可以转义中的分隔符字符 使用bash的变量

不,因为您从变量传递字符串,所以无法轻松转义分隔符字符,因为在
“s/$from/$to/”
中,分隔符不仅可以出现在
$to
部分中,还可以出现在
$from
部分中。例如,当您在
$from
部分中退出分隔符时,它根本不会进行替换,因为它不会从
中找到
$from

解决方案:使用其他工具,如
sed

1.)使用纯bash。在上面的脚本中,使用

    final=${string//$from/$to}
2.)如果bash的替换还不够,请使用可以将
$from
$to
作为变量传递的内容

  • 正如@anubhava已经说过的,可以使用:
    awk-vf=“$from”-vt=“$to”{gsub(f,t)}1”文件

  • 或者您可以使用
    perl
    并将值作为环境变量传递

  • 或者通过命令行参数将变量传递给perl
2种选择:

1) 获取一个不在字符串中的字符(需要内容检查的预处理和可能的字符,但不保证字符可用)

2) 在字符串模式中转义想要的字符(需要一个预处理来转义字符)


man sed

使用路径时,我经常使用
#
作为分隔符:

sed s\#find/path#replace/path#
无需使用丑陋的
\/
逃逸
/

    final=${string//$from/$to}
final=$(echo "$string" | perl_from="$from" perl_to="$to" perl -pe 's/$ENV{perl_from}/$ENV{perl_to}/')
final=$(echo "$string" | perl -spe 's/$f/$t/' -- -f="$from" -t="$to")
# Quick and dirty sample using `'/_#@|!%=:;,-` arbitrary sequence

Separator="$( printf "%sa%s%s" '/_#@|!%=:;,-' "${regexp}" "${replacement}" \
 | sed -n ':cycle
     s/\(.\)\(.*a.*\1.*\)\1/\1\2/g;t cycle
     s/\(.\)\(.*a.*\)\1/\2/g;t cycle
     s/^\(.\).*a.*/\1/p
    ' )"
echo "Separator: [ ${Separator} ]"
sed "s${Separator}${regexp}${Separator}${replacement}${Separator}flag" YourFile
# Quick and dirty sample using # arbitrary with few escape security check
regexpEsc="$( printf "%s" "${regexp}" | sed 's/#/\\#/g' )"
replacementEsc"$( printf "%s" "${replacement}" | sed 's/#/\\#/g' )"
sed 's#regexpEsc#replacementEsc#flags' YourFile
\cregexpc  
          Match lines matching the regular expression regexp.  The  c  may  be  any
          character.
sed s\#find/path#replace/path#