使用awk从文件中提取特定行

Dav*_*agh 8 awk line

我有两个文件,一个文件是我的数据,另一个文件是我要从我的数据文件中提取的行号列表.我可以使用awk读取我的行文件,然后提取与行号匹配的行吗?

示例:数据文件:

This is the first line of my data
This is the second line of my data
This is the third line of my data
This is the fourth line of my data
This is the fifth line of my data
Run Code Online (Sandbox Code Playgroud)

行号文件

1
4
5
Run Code Online (Sandbox Code Playgroud)

输出:

This is the first line of my data
This is the fourth line of my data
This is the fifth line of my data
Run Code Online (Sandbox Code Playgroud)

我只使用命令行awk和sed来实现非常简单的东西.这是超出我的方式,我一直在谷歌搜索一个小时没有答案.

Pau*_*ce. 10

awk 'NR == FNR {nums[$1]; next} FNR in nums' numberfile datafile
Run Code Online (Sandbox Code Playgroud)

只需引用数组下标即可创建条目.循环遍历第一个文件,而NR(记录号)等于FNR(文件记录号),使用该next语句存储数组中的所有行号.之后,当FNR第二个文件出现在数组中时(true),将打印该行(这是"true"的默认操作).


Tho*_*hor 7

一种方式sed:

sed 's/$/p/' linesfile | sed -n -f - datafile
Run Code Online (Sandbox Code Playgroud)

您可以使用相同的技巧awk:

sed 's/^/NR==/' linesfile | awk -f - datafile
Run Code Online (Sandbox Code Playgroud)

编辑 - 巨大的文件替代品

关于大量的行,将整个文件保存在内存中是不明智的.在这种情况下,解决方案可以是对数字文件进行排序并一次读取一行.以下内容已经过GNU awk测试:

extract.awk

BEGIN {
  getline n < linesfile
  if(length(ERRNO)) {
    print "Unable to open linesfile '" linesfile "': " ERRNO > "/dev/stderr"
    exit
  }
}

NR == n { 
  print
  if(!(getline n < linesfile)) {
    if(length(ERRNO))
      print "Unable to open linesfile '" linesfile "': " ERRNO > "/dev/stderr"
    exit
  }
}
Run Code Online (Sandbox Code Playgroud)

像这样运行:

awk -v linesfile=$linesfile -f extract.awk infile
Run Code Online (Sandbox Code Playgroud)

测试:

echo "2
4
7
8
10
13" | awk -v linesfile=/dev/stdin -f extract.awk <(paste <(seq 50e3) <(seq 50e3 | tac))
Run Code Online (Sandbox Code Playgroud)

输出:

2   49999
4   49997
7   49994
8   49993
10  49991
13  49988
Run Code Online (Sandbox Code Playgroud)

  • `-f`开关采用`sed/awk`脚本的名称,当`-f`的参数是连字符(`-`)时,它意味着'sed/awk`应该从`stdin`读取脚本. (2认同)
  • 这意味着 /dev/stdin 用作文件......在这种情况下,awk 源代码。 (2认同)