追加到线是preceded其次为空行 [英] Append to line that is preceded AND followed by empty line
问题描述
我要追加一个星号线,但只有当上述线路为preceded的和的后跟空行(仅供参考,上述空行不会对他们有任何空格)
I need to append an asterisk to a line, but only if said line is preceded and followed by empty lines (FYI, said empty lines will NOT have any white space in them).
假设我有以下文件:
foo
foo
foo
foo
foo
我所要的输出是这样的:
I want the output to look like this:
foo
foo
foo
foo*
foo
我试图修改以下 AWK
命令(找到<一href=\"http://stackoverflow.com/questions/21517723/sed-replace-pattern-only-if-followed-by-empty-line\">here):
awk 'NR==1 {l=$0; next}
/^$/ {gsub(/test/,"xxx", l)}
{print l; l=$0}
END {print l}' file
适合我的用途,但在节得到了所有捆绑起来。
to suit my uses, but got all tied up in knots.
桑达或Perl的解决方案,当然,也欢迎!
Sed or Perl solutions are, of course, welcome also!
更新:
原来,我问的问题是不太正确的。我真正需要的是code,将文本追加到非空行不以空格开始,并紧随其后,两行下,由非空行也不会与空白开始。
It turned out that the question I asked was not quite correct. What I really needed was code that would append text to non-empty lines that do not start with whitespace AND are followed, two lines down, by non-empty lines that also do not start with whitespace.
有关这个修订问题,假设我有以下文件:
For this revised problem, suppose I have the following file:
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
我所要的输出是这样的:
I want the output to look like this:
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
有关的是的,这个sed的一个班轮的伎俩:
For that, this sed one-liner does the trick:
sed '1N;N;/^[^[:space:]]/s/^\([^[:space:]].*\o\)\(\n\n[^[:space:]].*\)$/\1bar\2/;P;D' infile
由于以下本杰明W.的明确和翔实的答案,我能凑齐这一行!
Thanks to Benjamin W.'s clear and informative answer below, I was able to cobble this one-liner together!
推荐答案
一个sed的解决方案:
A sed solution:
$ sed '1N;N;s/^\(\n.*\)\(\n\)$/\1*\2/;P;D' infile
foo
foo
foo
foo*
foo
N;磷;ð
是通过附加的下一个模式空间,然后打印和删除先来看看在同一时间两行的惯用方式行。
N;P;D
is the idiomatic way to look at two lines at the same time by appending the next one to the pattern space, then printing and deleting the first line.
1N; N,P; d
扩展了总是在模式空间,这就是我们要在这里
1N;N;P;D
extends that to always having three lines in the pattern space, which is what we want here.
的替代,如果第一个和最后一行是空的( ^ \\ n
和 \\ N $
),并匹配附加有一个 *
来的空行之间的界限。
The substitution matches if the first and last line are empty (^\n
and \n$
) and appends one *
to the line between the empty lines.
注意,这个匹配,并附加 *
也为三个空行的第二行,你想要什么这可能不是。为了确保这种情况不会发生,第一个捕获组必须至少有一个非空白字符:
Notice that this matches and appends a *
also for the second line of three empty lines, which might not be what you want. To make sure this doesn't happen, the first capture group has to have at least one non-whitespace character:
sed '1N;N;s/^\(\n[^[:space:]].*\)\(\n\)$/\1*\2/;P;D' infile
从评论的问题
我们能不的追加 *
如果线两条以上 ABC
开始?
Question from comment
Can we not append the *
if the line two above begins with abc
?
例输入文件:
foo
foo
abc
foo
foo
foo
foo
有三种富
空行之间,但第一个不应该得到的 *
追加因为线路上述两个与 ABC
启动。这是可以做到如下:
There are three foo
between empty lines, but the first one should not get the *
appended because the line two above starts with abc
. This can be done as follows:
$ sed '1{N;N};N;/^abc/!s/^\(.*\n\n[^[:space:]].*\)\(\n\)$/\1*\2/;P;D' infile
foo
foo
abc
foo
foo*
foo*
foo
本保持的在模式空间中时四驱的线,不仅使替换如果模式空间不与启动ABC
:
This keeps four lines at a time in the pattern space and only makes the substitution if the pattern space does not start with 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
二备注:
- BSD的sed需要一个额外的分号:
1 {N; N;}
而不是1 {N; N}
。 -
如果该文件的第一行和第三行是空的,第二行则的不的获得一个星号追加,因为我们才开始有四行模式空间检查一次。
- BSD sed requires an extra semicolon:
1{N;N;}
instead of1{N;N}
. If the first and third line of the file are empty, the second line does not get an asterisk appended because we only start checking once there are four lines in the pattern space. This could be solved by adding an extra substitution into the
1{}
block:
1{N;N;s/^\(\n[^[:space:]].*\)\(\n\)$/\1*\2/}
(记住额外的;
为BSD SED),而是试图覆盖所有的边缘情况使得sed的就更少了可读性,尤其是在单行:
(remember the extra ;
for BSD sed), but trying to cover all edge cases makes sed even less readable, especially in one-liners:
sed '1{N;N;s/^\(\n[^[:space:]].*\)\(\n\)$/\1*\2/};N;/^abc/!s/^\(.*\n\n[^[:space:]].*\)\(\n\)$/\1*\2/;P;D' infile
这篇关于追加到线是preceded其次为空行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!