awk 根据条件开始打印

leo*_*nko 4 bash awk

我在文件中有测试数据 text.txt

a
b
test
test2
1,2
3,3
Run Code Online (Sandbox Code Playgroud)

我想从 test 为 + 2 的行号开始输出文件。我需要这是一个可用的单行gnuplot,我想出了以下内容:

awk -v linestart=$(awk '$0~"test" {a=NR}END{print a+2}' $filename) 'BEGIN{FS=",";OFS="\t";lines}NR>=linestart{print $1, $2}' $filename
Run Code Online (Sandbox Code Playgroud)

但我需要以某种方式将文件内容提供给两个awk我不知道该怎么做的。所以我想出了解决方案,$filename但这有问题,如何进入$filename

我在想:

echo "test.txt" | read filename | awk -v linestart=$(awk '$0~"test" {a=NR}END{print a+2}' $filename) 'BEGIN{FS=",";OFS="\t";lines}NR>=linestart{print $1, $2}' $filename
Run Code Online (Sandbox Code Playgroud)

但这不起作用。

我还能如何使上述工作?明显的问题是我需要在运行之前知道要开始打印的行号awk。我也在想一些事情:

awk 'BEGIN{FS=",";OFS="\t";lines=100000}{if ($0~"test"){lines=NR+2}; if(NR>=lines){print $1, $2}}' 
Run Code Online (Sandbox Code Playgroud)

但是我什至没有尝试过,因为它非常丑陋且不通用,我必须使变量lines始终足够大。那么是否有一个优雅的解决方案可以与普通的文本文件管道一起使用,或者在其他情况下以某种方式将文件名推入其中?

Kus*_*nda 6

使用ed

$ printf '%s\n' '/^test/+2,$p' | ed -s file
1,2
3,3
Run Code Online (Sandbox Code Playgroud)

ed编辑器中,该命令/^test/+2,$p将打印 ( p) 从匹配行之外的两行^test到结尾 ( $) 的行。

使用awk

$ awk '/^test/ { flag = 1; count = 1 }; (flag == 1 && count <= 0); { count-- }' file
1,2
3,3
Run Code Online (Sandbox Code Playgroud)

在这里,如果flag是 1 并且如果count小于或等于零,将打印一行。当^test输入数据中的模式匹配时,标志设置为 1 ,count然后还设置为要跳过的行数,直到输出开始(不计算当前行)。在count所有行降低。

一种稍微不同的方法awk

$ awk '/^test/ { getline; while (getline > 0) print }' file
1,2
3,3
Run Code Online (Sandbox Code Playgroud)

在这里,我们匹配我们的模式,然后立即读取并丢弃下一行输入。然后我们使用 while 循环读取文件的其余部分,打印读取的每一行。

完全相同的方法,但具有sed

$ sed -n -e '/^test/ { n' -e ':again' -e 'n; p; b again' -e '}' file
1,2
3,3
Run Code Online (Sandbox Code Playgroud)

匹配模式,然后读取并丢弃下一行 ( n),然后进入循环读取并打印每一行 ( n; p;)。循环由标签again和分支/跳转到该标签 ( b again) 组成。