我有一个大约有 1500 万行的大文件。奇数行包含键(但不仅仅是键),偶数行是数据。也就是说,该文件类似于:
WRTZ Tyrosine
1287998798
ASDF Proline
9408654860
TYSR Serine
9809804090
ASDF Cytosine
4950409808
这里的键是ASDF
、TYSR
、 和WRTZ
。
我有大约 100000 个键的列表。我想提取与这些键对应的数据(两行)。
我尝试的一种方法是在grep
包含键的行中获取行号,然后在循环中使用head
and提取该行和下一行。tail
然而,这似乎需要很长时间才能运行。
有没有更有效的方法来做到这一点?
答案1
如果偶数行和奇数行没有变化。然后尝试使用下面的命令
awk 'NR%2{printf $1"-";next;}1' <Filename>
上述命令的输出将是
WRTZ-1287998798
ASDF-9408654860
TYSR-9809804090
ASDF-4950409808
答案2
一个小的 awk 脚本就可以完成这项工作。通过阅读 awk man 手册很容易理解。
#!/usr/bin/awk -f
BEGIN{got=0;linenum=0}
/ASDF/{printf ("%s ",$1); got=1;linenum=NR+1}
/TYSR/{printf ("%s ",$1); got=1;linenum=NR+1}
/WRTZ/{printf ("%s ",$1); got=1;linenum=NR+1}
/^[0-9]/{if ( ( got == 1 ) && ( linenum == NR) ) {
printf("%s\n",$1)
got=0
linenum=0
}}
输出将是这样的:
./awk_script data_file
WRTZ 1287998798
ASDF 9408654860
TYSR 9809804090
ASDF 4950409808
您可以修改它以满足您自己的需要!
答案3
您最可能想要的是利用grep
,及其本机选项来显示比赛周围的 +/- 线:
Context Line Control
-A NUM, --after-context=NUM
Print NUM lines of trailing context after matching lines. Places a line containing a group separator (--) between contiguous
groups of matches. With the -o or --only-matching option, this has no effect and a warning is given.
-B NUM, --before-context=NUM
Print NUM lines of leading context before matching lines. Places a line containing a group separator (--) between contiguous
groups of matches. With the -o or --only-matching option, this has no effect and a warning is given.
-C NUM, -NUM, --context=NUM
Print NUM lines of output context. Places a line containing a group separator (--) between contiguous groups of matches. With
the -o or --only-matching option, this has no effect and a warning is given.
答案4
使用乐(以前称为 Perl_6)
如果您正在寻找配对线路,那么rotor
/batch
它们:
~$ raku -e '.put for lines.rotor(2, partial => True).map: *.words[0,2];' file
#OR
~$ raku -e '.put for lines.batch(2).map: *.words[0,2];' file
Raku 的rotor
/batch
例程可以采用用户定义数量(例如2
3、4 等)的元素(例如lines
)并将它们分组在一起。如果您预期完整的配对(即文件包含偶数行),您可以简单地使用rotor
并删除该partial => True
参数。
注意:此代码根据空格分隔的.words
标准保留元素。如果(比方说)某些对words
在第一行有两个,而其他对words
在第一行有三个(或更多),您可能会遇到问题。
您可以通过选择第一个word
来避免此问题每个线,像这样:
~$ raku -e '.put for lines.rotor(2).map( *.map: *.words[0]);' file
#OR (using `>>` hyper notation):
~$ raku -e '.put for lines.rotor(2)>>.map: *.words[0];' file
输入示例:
WRTZ Tyrosine
1287998798
ASDF Proline
9408654860
TYSR Serine
9809804090
ASDF Cytosine
4950409808
示例输出(所有代码示例):
WRTZ 1287998798
ASDF 9408654860
TYSR 9809804090
ASDF 4950409808