如何使用 awk 使用另一个文件中的数字从文件中正确提取行?

如何使用 awk 使用另一个文件中的数字从文件中正确提取行?

我正在使用 bash shell。如果我有一个行号文件

1
4
7
9

和另一个行文件,其中第一个元素是数字,后跟文本字符串

1,Michael Jordan
2,Karl Malone,
3,Charles Barkley
4,Greg Anthony
5,Chris Mullen
6,Reggie Miller
7,Billy Owens
8,David Robinson
9,Shaquille O'Neal
10,John Stockton

awk仅当第一个数字属于第一个文件时,如何编写命令以从第二个文件中提取行?在上面的例子中,我期望这个结果

1,Michael Jordan
4,Greg Anthony
7,Billy Owens
9,Shaquille O'Neal

我试过这个

awk 'FNR==NR{a[$1];next} $1 in a' /tmp/first_file /tmp/second_file > /tmp/third_file

但它在第三个文件中什么也没产生。

答案1

由于您的第二个文件是逗号分隔的,因此您需要使用命令行选项将 awk 字段分隔符设置为,- :-F

awk -F, 'FNR==NR{a[$1];next} $1 in a' /tmp/first_file /tmp/second_file > /tmp/third_file

或通过FS内置变量:

awk 'FNR==NR{a[$1];next} $1 in a' /tmp/first_file FS=, /tmp/second_file > /tmp/third_file

后一种方法将允许您处理第一个文件不是逗号分隔(并且有多个字段)的情况。

答案2

使用(以前称为 Perl_6)

~$ raku -ne 'BEGIN my @a = "nbr_list.txt".IO.lines.map: *.Int;  \
             .put if $_.split(",")[0] == any(@a);'  file.csv

#OR

~$ raku -ne 'BEGIN my @a = "nbr_list.txt".IO.lines.map: *.Int;  \
             .put if $_.split(",")[0] ~~ any(@a);'  file.csv

Raku 是 Perl 家族的一种编程语言。当您 时BEGIN,获取数字列表并将其存储在数组中@a。然后,标志-ne从命令行读取文件,而不自动打印(awk类似行为)。

此处,该行被读入主题变量 ( $_)(位于逗号上),并获取split第一个元素 ( )。使用数值相等运算符(第一个代码示例)或 Raku 的智能匹配运算符来[0]比较这些元素。在操作员的右侧,阵列变成了结点。如果满足条件,则条件输出该行。==~~@aany()ifput

输入示例:

1,Michael Jordan
2,Karl Malone,
3,Charles Barkley
4,Greg Anthony
5,Chris Mullen
6,Reggie Miller
7,Billy Owens
8,David Robinson
9,Shaquille O'Neal
10,John Stockton

示例输出(使用nbr_list.txt由 1,4,7,9 组成的文件):

1,Michael Jordan
4,Greg Anthony
7,Billy Owens
9,Shaquille O'Neal

连接点很有趣,因为它们会自动线程化。对于上述问题,one()连接器也可以工作,甚至可能更有效。


另一种方法是使用集合:将行号转换为 a Setof Ints。数据按行读取,每个第一列都被强制为Int,并检查它是否是(elem)集合的元素。请注意,以下代码中可以使用infix(elem)或 infix , (Unicode 符号):

~$ raku -ne 'BEGIN my $set1 = Set.new("nbr_list.txt".IO.lines.map: *.Int);  \
             .put if $_.split(",").[0].Int (elem) $set1;'  file

由于 Raku Sets 只能包含唯一值(即它们“唯一化”输入),因此第二个示例将丢弃文件中的重复项"nbr_list.txt"。这确实可能是OP所希望的。

https://docs.raku.org/type/Junction
https://docs-stage.raku.org/type/Junction
https://raku.org

答案3

这种操作称为“连接”。 coreutils 中有一个工具用于join连接文本文件。

join -t, -j1 --nocheck-order first_file second_file
1,Michael Jordan
4,Greg Anthony
7,Billy Owens
9,Shaquille O'Neal

解释:

  1. -t,- 使用逗号作为字段分隔符
  2. -j1- 加入第一个字段
  3. --nocheck-order- join 需要对文件进行排序,但它不喜欢数字排序。因此,我们阻止它检查字典排序并抱怨“9”前置“10”。只要两个文件中的第一列使用相同的算法排序,它仍然有效。

相关内容