假设我有一个输入文件,其内容为
cat file
[source,I]
[source,more]
[source,1234]
[source,content]
首先观察两个空行,然后是以[source
开头的模式,然后从后续点开始单个空行。我想删除一个或多个空行后跟一个模式(或者删除,删除一个以[source
开头的模式上方的一个或多个空行)。我希望输出为
[source,I]
[source,more]
[source,1234]
[source,content]
我制定了Awk
逻辑
awk '!NF{getline n; if ( match(n, /^\[source/) ) {print n}}' file
除了它跳过了两个空行之后的模式并产生输出
之外,它完美地工作[source,more]
[source,1234]
[source,content]
我尝试通过打印getline()
Awk
应该已完成match()
并打印该行的行NR来解决awk '!NF{getline n; if ( match(n, /^\[source/) ) {print n} else {print NR}}' file
2 # Why did this fail for NR==2?
[source,more]
[source,1234]
[source,content]
调用失败的原因,
NR==2
想知道当getline()
应该返回[source,I]
并且在匹配正则表达式后打印相同内容时,$ awk --version
GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.4-p1, GNU MP 6.1.1)
失败的原因。
{{1}}
答案 0 :(得分:3)
如果您预先添加调试打印,您可以看到发生了什么:
$ awk '{print ">", NR, NF, $0} !NF{getline n; if ( match(n, /^\[source/) ) {print n} else {print NR}}' file
> 1 0
2
> 3 1 [source,I]
> 4 0
[source,more]
> 6 0
[source,1234]
> 8 0
[source,content]
所以awk读取为空的第1行,因此!NF
为真所以它会读取第2行的getline,它也是空的,它不匹配()而是打印当前的行号,这是2。
现在awk读取第3行[source,I]
,这是非空的,因此!NF
为假,因此不执行动作块,并且只丢弃第3行。
现在awk读取第4行....依此类推。
当然,对于像这样的问题,getline是错误的方法,一旦你修改了你的样本输入/输出,我们就可以向你展示如何以正确的方式做你想做的事情,但是这样的声音你就是这样的真的想做:
$ awk 'NF{if (/^\[source/) print buf $0; buf=""; next} {buf = buf $0 ORS}' file
[source,I]
[source,more]
[source,1234]
[source,content]
答案 1 :(得分:2)
如果getline
是强制性的,您可以在do ... while
gawk
进行尝试
awk '!NF{
do getline n; while(length(n)==0);
if ( match(n, /^\[source/) ) print n}' file
你明白了,
[source,I]
[source,more]
[source,1234]
[source,content]
答案 2 :(得分:1)
@Inian:当然它只打印第二行号,因为getline n表示光标从第1行进入下一行,显然当它进入第2行时,如果你打印NR,它将只打印第2行。 所以当光标到达第一行时它会看到!NF然后进入它然后getline确保它应该转到第二行并将它的值存储到n所以第二行也是空的所以它将打印那里的行数。
建议代码恕我直言:
awk '!NF{getline n; if ( match(n, /^\[source/) ) {print n} else {print NR};next} NF' Input_file
通过对代码进行微小更改,您将能够获得代码中缺少的第3个源代码行。所以在这里你要检查NF是否为NULL,当1为空时它将起作用,接着是下面的源行将工作,即使你有n个空行然后是源行。因此,在NF条件下,在上面和后面添加NF也应该可以解决问题。
如果不需要,您可以删除上面的打印NR。如果我在这里遗漏了一些内容,我很抱歉,请告诉我这是否有帮助。
编辑:当Inian问为什么它在第二行失败时,让我试一试,如果我正确理解问题并且可以在这里解释。awk '!NF ###### !NF, checking that if any line is empty or not, if it is empty then do following.
{getline n; ###### getline n, means go to next line(which will be 2nd line now) and have it's value into variable named n.
if ( match(n, /^\[source/) ) ###### if n matches the regex pattern then do following, NOTE as n is EMPTY in case of 2nd line is empty,
so it will NOT pass the if condition it will go to else and print the line number which is 2.
{print n} else {print NR}}' ###### printing n in case if condition is TRUE. using else if above condition is NOT true.