您可以通过一次sed
调用来处理两种情况(在一个连续的块中包含注释行,或在未注释的行之间散布):
sed '1,/PATTERN/{/^#/{x;1d;b};//!{H;/PATTERN/!{1h;d};//{x;s/\n/&#/g}}}' infile
这仅处理1,/PATTERN/
范围内的线。它x
改变保持空间w。每次注释一行时的模式空间(因此,保留缓冲区中的注释行永远不会超过一条),并将未注释的每一行追加到H
旧空间(1d
分别在第一行和第二行时,1h
以删除初始行)保留缓冲区中的空行)。
当到达匹配PATTERN的行时,它还会将其追加到H
旧缓冲区,e x
更改缓冲区,然后用ewline和a 替换\n
模式空间中的每个ewline字符(也就是说,模式空间中的所有行现在都以,包括第一行在内的第一行始终是带注释的行)。\n
#
#
附带样品infile
:
alice
#bob
bill
#charlie
ding
dong
dotan
jimmy
#garry
运行:
sed '1,/dotan/{ # if line is in this range -start c1
/^#/{ # if line is commented -start c2
x # exchage hold space w. pattern space
1d # if 1st line, delete pattern space
b # branch to end of script
} # -end c2
//!{ # if line is not commented -start c3
H # append to hold space
/dotan/!{ # if line doesn't match dotan -start c4
1h # if 1st line, overwrite hold space
d # delete pattern space
} # -end c4
//{ # if line matches dotan -start c5
x # exchage hold space w. pattern space
s/\n/&#/g # add # after each newline character
} # -end c5
} # -end c3
}' infile # -end c1
输出:
alice
#bob
bill
#charlie
#ding
#dong
#dotan
jimmy
#garry
因此,它仅注释从(并排除)#charlie
到(并包括)直到(包括)dotan
的所有行,而其他行则保持不变。
当然,这是假设在match之前总是至少有一条注释行PATTERN
。如果不是这种情况,您可以在替换之前添加其他支票:/^#/{s/\n/&#/g}