我的文件中有测试数据text.txt
a
b
test
test2
1,2
3,3
我想输出从 test 为 + 2 的行号开始的文件。我需要将其作为可在 中使用的 oneliner 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
但我需要以某种方式将文件内容提供给两个,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
但这不起作用。
我还能如何使上述工作正常进行?明显的问题是我需要在运行之前知道要开始打印的行号awk
。我也在思考一些事情:
awk 'BEGIN{FS=",";OFS="\t";lines=100000}{if ($0~"test"){lines=NR+2}; if(NR>=lines){print $1, $2}}'
但我什至没有尝试过,因为它非常丑陋而且不通用,我必须使变量lines
始终足够大。那么是否有一个优雅的解决方案可以与普通的文本文件管道一起使用,或者在其他情况下通过某种方式将文件名推入其中?
答案1
使用ed
:
$ printf '%s\n' '/^test/+2,$p' | ed -s file
1,2
3,3
在ed
编辑器中,该命令/^test/+2,$p
将打印 ( p
) 匹配 , 行之外的两行^test
到结尾 ( $
) 的行。
使用awk
:
$ awk '/^test/ { flag = 1; count = 1 }; (flag == 1 && count <= 0); { count-- }' file
1,2
3,3
flag
这里,如果is 1 并且count
小于或等于 0,则会打印一行。当模式^test
在输入数据中匹配时,该标志设置为 1 ,count
然后还设置为在输出开始之前要跳过的行数(不计算当前行)。count
所有线路的值都会减少。
略有不同的方法awk
:
$ awk '/^test/ { getline; while (getline > 0) print }' file
1,2
3,3
在这里,我们匹配我们的模式,然后立即读取并丢弃下一行输入。然后我们使用 while 循环来读取文件的其余部分,打印读取的每一行。
完全相同的方法,但使用sed
:
$ sed -n -e '/^test/ { n' -e ':again' -e 'n; p; b again' -e '}' file
1,2
3,3
匹配模式,然后读取并丢弃下一行 ( n
),然后进入循环读取并打印每一行 ( n; p;
)。循环由标签again
和分支/跳转到该标签 ( )组成b again
。
答案2
如果你知道你的数据在 后 2 行开始test
,并且上面没有更多行test
,你可以这样做:
awk '/^test$/ { f=1 } f && f++ > 2' filename
另外,要将此数据发送到 Gnuplot,您可以考虑通过如下管道进行操作:
(
echo "set datafile separator ','"
echo "plot '-' using 1:2 with lines"
awk '/^test$/ { f=1 } f && f++ > 2' filename
echo "e"
) | gnuplot -persist
答案3
您可以简单地使用一个start, end
范围来实现这一点,该范围的结束条件始终为 false,并且开始条件会跳过行:
awk '/test/ && getline && getline, 0'
答案4
$ awk '/test/{n=NR} n && NR>n' file
1,2
3,3
$ awk '/test/{n=NR+1} n && NR>n' file
3,3