11

我有两个文件,一个文件是我的数据,另一个文件是我想从数据文件中提取的行号列表。我可以使用 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

行号文件

1
4
5

输出:

This is the first line of my data
This is the fourth line of my data
This is the fifth line of my data

我只使用过命令行 awk 和 sed 来处理非常简单的事情。这超出了我的范围,我已经在谷歌上搜索了一个小时而没有答案。

4

6 回答 6

11
awk 'NR == FNR {nums[$1]; next} FNR in nums' numberfile datafile

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

于 2012-08-29T18:59:44.770 回答
10

一种方法sed

sed 's/$/p/' linesfile | sed -n -f - datafile

您可以使用相同的技巧awk

sed 's/^/NR==/' linesfile | awk -f - datafile

编辑 - 巨大的文件替代

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

提取.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
  }
}

像这样运行它:

awk -v linesfile=$linesfile -f extract.awk infile

测试:

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

输出:

2   49999
4   49997
7   49994
8   49993
10  49991
13  49988
于 2012-08-29T17:06:44.543 回答
1

这是一个 awk 示例。预先加载输入文件,然后输出匹配的数据文件记录。

awk \
  -v RS="[\r]*[\n]" \
  -v FILE="inputfile" \
  'BEGIN \
   {
     LINES = ","
     while ((getline Line < FILE))
     {
       LINES = LINES Line ","
     }
   }
   LINES ~ "," NR "," \
   {
     print
   }
  ' datafile
于 2012-08-29T17:20:06.327 回答
1

我有同样的问题。这是 Thor 已经发布的解决方案:

cat datafile \
| awk 'BEGIN{getline n<"numbers"} n==NR{print; getline n<"numbers"}'

如果像我一样您没有数字文件,而是从标准输入传递过来并且您不想生成临时数字文件,那么这是一种替代解决方案:

cat numbers \
| awk '{while((getline line<"datafile")>0) {n++; if(n==$0) {print line;next}}}'
于 2014-07-05T17:31:23.357 回答
0
while read line; do echo $(sed -n '$(echo $line)p' Datafile.txt); done < numbersfile.txt
于 2014-06-12T12:00:42.387 回答
0

这个解决方案...

awk 'NR == FNR {nums[$1]; next} FNR in nums' numberfile datafile

...仅打印数字文件中的唯一数字。如果 numberfile 包含重复的条目怎么办?然后 sed 是一个更好的(但慢得多)的选择:

sed -nf <(sed 's/.*/&p/' numberfile) datafile

于 2019-04-03T16:00:40.447 回答