我需要替换文件中的模式,只有后面跟一个空行。假设我有以下文件:
test
test
test
...
以下命令会将所有test
替换为xxx
cat file | sed 's/test/xxx/g'
但如果下一行为空,我只需要替换test
。我尝试过匹配hex code
,但这不起作用:
cat file | sed 's/test\x0a/xxx/g'
所需的输出应如下所示:
test
xxx
xxx
...
答案 0 :(得分:3)
sed
,perl
和awk
的建议解决方案:
<强> SED 强>
sed -rn '1h;1!H;${g;s/test([^\n]*\n\n)/xxx\1/g;p;}' file
我从sed multiline search and replace得到了这个想法。基本上将整个文件啜饮到sed的保留空间中,并立即对整个块进行全局替换。
<强> perl的强>
$ perl -00 -pe 's/test(?=[^\n]*\n\n)$/xxx/m' file
-00
触发段落模式,这使得perl读取块被一个或多个空行分隔(正是OP正在寻找的)。积极向前看(?=)
以将替换锚定到块的最后一行。
警告: -00
会将多个空行压缩成单个空行。
<强> AWK 强>
$ awk 'NR==1 {l=$0; next}
/^$/ {gsub(/test/,"xxx", l)}
{print l; l=$0}
END {print l}' file
基本上存储l
中的上一行,如果当前行为空,则替换l
中的模式。打印l
。最后打印最后一行。
所有三种情况下的输出
test
xxx
xxx
...
答案 1 :(得分:2)
使用sed
sed -r ':a;$!{N;ba};s/test([^\n]*\n(\n|$))/xxx\1/g'
解释
:a # set label a
$ !{ # if not end of file
N # Add a newline to the pattern space, then append the next line of input to the pattern space
b a # Unconditionally branch to label. The label may be omitted, in which case the next cycle is started.
}
# simply, above command :a;$!{N;ba} is used to read the whole file into pattern.
s/test([^\n]*\n(\n|$))/xxx\1/g # replace the key word if next line is empty (\n\n) or end of line ($)
答案 2 :(得分:2)
这可能适合你(GNU sed):
sed -r '$!N;s/test(\n\s*)$/xxx\1/;P;D' file
在整个文件长度上保留一个2行的窗口,如果第二行为空,第一行包含该模式,则进行替换。