用户指定replacestring的sedreplace

sed中 replace命令的一般forms是:

s/regexp/replacement/flags 

其中“/”字符可以被任何其他单个字符统一replace。 但是,如果replacestring由环境variables提供并且可能包含任何可打印字符,那么如何select此分隔符? 有没有一种简单的方法来使用bash转义variables中的分隔符?

值来自受信任的pipe理员,所以安全性不是我主要关心的。 (换句话说,请不要回答:“不要这样做!”)然而,我无法预测replacestring中需要显示哪些字符。

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

 s^Aregexp^Areplacement^Ag 

其中^ACTRL v一起按下。

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

 awk -vs="search" -vr="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 

什么打印

 in [=xxx=] want replace [xxx] to [===] wanted result: [=====] OK in [=abc=] want replace [abc] to [///] wanted result: [=///=] sed: 1: "s/abc/////": bad flag in substitute command: '/' WRONG in [=///=] want replace [///] to [abc] wanted result: [=abc=] sed: 1: "s/////abc/": bad flag in substitute command: '/' WRONG 

不能抗拒: 不要这样做! (与sed)。 🙂

有没有一种简单的方法来使用bash转义变量中的分隔符?

不,因为你从变量传递字符串,你不能轻易地转义分隔符,因为在"s/$from/$to/"分隔符不仅可以出现在$to部分,而且也可以出现在$from部分。 例如,当你逃离分隔符时,它在$from部分根本不会做替换,因为不会找到$from

解决方案:使用其他的东西

1)使用纯粹的bash。 在上面的脚本中,而不是使用sed

  final=${string//$from/$to} 

2.)如果bash的替换不够用,可以使用$to$to作为变量。

  • 作为@anubhava已经说过,可以使用: awk -vf="$from" -vt="$to" '{gsub(f, t)} 1' file

  • 或者你可以使用perl和传值作为环境变量

 final=$(echo "$string" | perl_from="$from" perl_to="$to" perl -pe 's/$ENV{perl_from}/$ENV{perl_to}/') 
  • 或通过命令行参数将变量传递给perl
 final=$(echo "$string" | perl -spe 's/$f/$t/' -- -f="$from" -t="$to") 

2个选项:

1)不要在字符串中的字符(需要预处理内容检查和可能的字符,没有保证字符可用)

 # 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 

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

 # 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