我想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
,但它可以更长/更具可读性) - 它们不会出现在其他变量中:
orig
、new
或Initial
Final
- 和以前一样,它们不包含会破坏
sed
表达式的字符