附加到前面的行,后跟空行

Dig*_*ger 1 perl awk sed

我需要一个星号追加到一条线,但只有当上述线路的前面后面的空行(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.在下面的清晰且内容丰富的答案,我能够将这个单行程拼凑在一起!

Ben*_* W. 5

一个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. BSD sed需要额外的分号:1{N;N;}而不是1{N;N}.
  2. 如果该文件的第一行和第三行是空的,第二行则没有得到一个星号追加,因为我们才开始有四行模式空间检查一次.这可以通过在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)