我需要一个星号追加到一条线,但只有当上述线路的前面和后面的空行(FYI,表示空行不会对他们有任何空白).
假设我有以下文件:
foo
foo
foo
foo
foo
Run Code Online (Sandbox Code Playgroud)
我希望输出看起来像这样:
foo
foo
foo
foo*
foo
Run Code Online (Sandbox Code Playgroud)
我尝试修改以下awk命令(在此处找到):
awk 'NR==1 {l=$0; next}
/^$/ {gsub(/test/,"xxx", l)}
{print l; l=$0}
END {print l}' file
Run Code Online (Sandbox Code Playgroud)
为了适应我的用途,但所有人都被束缚了.
当然,Sed或Perl解决方案也是受欢迎的!
更新:
事实证明,我问的问题并不完全正确.我真正需要的是将文本附加到非空白行的代码,这些行不是以空格开头并且后面跟着,两行向下,非空行也不是以空格开头.
对于此修订的问题,假设我有以下文件:
foo
third line foo
fifth line foo
this line starts with a space foo
this line starts with a space foo
ninth line foo
eleventh line foo
this line starts with a space foo
last line foo
Run Code Online (Sandbox Code Playgroud)
我希望输出看起来像这样:
foobar
third line foobar
fifth line foo
this line starts with a space foo
this line starts with a space foo
ninth line foobar
eleventh line foo
this line starts with a space foo
last line foo
Run Code Online (Sandbox Code Playgroud)
对于这,这sed的一个班轮的伎俩:
sed '1N;N;/^[^[:space:]]/s/^\([^[:space:]].*\o\)\(\n\n[^[:space:]].*\)$/\1bar\2/;P;D' infile
Run Code Online (Sandbox Code Playgroud)
感谢Benjamin W.在下面的清晰且内容丰富的答案,我能够将这个单行程拼凑在一起!
一个sed解决方案:
$ sed '1N;N;s/^\(\n.*\)\(\n\)$/\1*\2/;P;D' infile
foo
foo
foo
foo*
foo
Run Code Online (Sandbox Code Playgroud)
N;P;D 是通过将下一行添加到模式空间,然后打印和删除第一行来同时查看两行的惯用方法.
1N;N;P;D 将其扩展为在模式空间中始终具有三条线,这就是我们想要的.
如果第一行和最后一行为空(^\n和\n$),则替换匹配,并将*一行附加到空行之间的行.
请注意,这匹配并附加了*三个空行的第二行,这可能不是您想要的.为确保不会发生这种情况,第一个捕获组必须至少有一个非空白字符:
sed '1N;N;s/^\(\n[^[:space:]].*\)\(\n\)$/\1*\2/;P;D' infile
Run Code Online (Sandbox Code Playgroud)
我们能不能追加*,如果线两条以上开始abc?
示例输入文件:
foo
foo
abc
foo
foo
foo
foo
Run Code Online (Sandbox Code Playgroud)
foo空行之间有三个,但第一个不应该*附加,因为上面的第二行以abc.这可以按如下方式完成:
$ sed '1{N;N};N;/^abc/!s/^\(.*\n\n[^[:space:]].*\)\(\n\)$/\1*\2/;P;D' infile
foo
foo
abc
foo
foo*
foo*
foo
Run Code Online (Sandbox Code Playgroud)
这使4线在模式空间时,只有使替代,如果模式空间不会启动abc:
1 { # On the first line
N # Append next line to pattern space
N # ... again, so there are three lines in pattern space
}
N # Append fourth line
/^abc/! # If the pattern space does not start with abc...
s/^\(.*\n\n[^[:space:]].*\)\(\n\)$/\1*\2/ # Append '*' to 3rd line in pattern space
P # Print first line of pattern space
D # Delete first line of pattern space, start next cycle
Run Code Online (Sandbox Code Playgroud)
两个评论:
1{N;N;}而不是1{N;N}.如果该文件的第一行和第三行是空的,第二行则没有得到一个星号追加,因为我们才开始有四行模式空间检查一次.这可以通过在1{}块中添加额外的替换来解决:
1{N;N;s/^\(\n[^[:space:]].*\)\(\n\)$/\1*\2/}
Run Code Online (Sandbox Code Playgroud)
(记住;BSD sed 的额外内容),但试图覆盖所有边缘情况使得sed更不易读,尤其是在单行中:
sed '1{N;N;s/^\(\n[^[:space:]].*\)\(\n\)$/\1*\2/};N;/^abc/!s/^\(.*\n\n[^[:space:]].*\)\(\n\)$/\1*\2/;P;D' infile
Run Code Online (Sandbox Code Playgroud)