懒惰法

懒惰法

我想abc将的所有实例替换为123,前提是它前面没有https://

代码:

file=Data.txt
Initial="# Start";
orig="abc";
new="123"; 

Final="$" # Line Number
sed -r -e "/${Initial}/,${Final}s/${orig}/${new}/g" ${file} # Final doesn't accept $

数据:

# Start

abc.md
https://abc.md
The path is https://abc.md for abc.md
The path for abc.md is https://abc.md 

预期输出:

# Start

123.md
https://abc.md
The path is https://abc.md for 123.md
The path for 123.md is https://abc.md 

我怎样才能实现这个目标?


注意:我还需要使用${Initial}${Final}来表示其之间可能存在模式。

这个答案不适用于此案例The path is: https://abc.md abc.md

答案1

您正在寻找的是消极向后看,既不支持sed也不awk支持。我建议使用perl,例如:

file=Data.txt
export Initial="# Start"
export orig="abc"
export new="123"
export Final="5"

perl -pe '
 $flag=1 if /$ENV{Initial}/;
 s,(?<!https://)$ENV{orig},$ENV{new},g if $flag;
 $flag=0 if $. == $ENV{Final};
' $file

答案2

您可以暂时将所有以 开头的实例更改https://为其他内容(不包含 )abc,并在完成后将它们更改回来。

懒惰法

sed -e 's_https://abc_protected_g;/# Start/,$s_abc_123_g;s_protected_https://abc_'

您必须为临时字符串选择一些值,您可以确定该值不会出现在您的输入中(并且不包含任何会干扰sed或外壳引用的特殊字符)。我用过protected,但建议使用更有特色的东西。

彻底的方法

如果您不能确定临时字符串不会出现在输入中,则更长但更安全的替代方法是使用替换字符串:

sed -e 's/X/Xv/g;s_https://abc_Xu_g;/^# Start/,$s/abc/123/g;s_Xu_https://abc_g;s/Xv/X/g'

这两个临时字符串的要求是:

  • 它们有一个共同的前缀(我使用了X,但它可以更长/更具可读性)
  • 它们不会出现在其他变量中:orignewInitialFinal
  • 和以前一样,它们不包含会破坏sed表达式的字符

相关内容