11

2 つのファイルがあります。1 つのファイルはデータで、もう 1 つのファイルはデータ ファイルから抽出する行番号のリストです。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 を本当に単純なものにしか使用したことがありません。これは私をはるかに超えており、答えなしで1時間グーグルで検索しています。

4

6 に答える 6

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

配列の添字を参照するだけでエントリが作成されます。NRwhile (record number) is equal to FNR(file record number) ステートメントを使用して最初のファイルをループすると、nextすべての行番号が配列に格納されます。その後FNR、2 番目のファイルが配列に存在する場合 (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

編集-巨大なファイルの代替

膨大な数の行に関しては、ファイル全体をメモリに保持するのは賢明ではありません。その場合の解決策は、数値ファイルを並べ替えて、一度に1行ずつ読み取ることです。以下はGNUawkでテストされています。

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
  }
}

次のように実行します。

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

私も同じ問題を抱えていました。これは、Thor によって既に投稿されたソリューションです。

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

私のように数値ファイルを持っていないが、代わりに stdin から渡され、一時的な数値ファイルを生成したくない場合は、これが代替ソリューションです。

cat numbers \
| awk '{while((getline line<"datafile")>0) {n++; if(n==$0) {print line;next}}}'
于 2014-07-05T17:31:23.357 に答える
1

awk の例を次に示します。inputfile が最初に読み込まれ、一致する datafile のレコードが出力されます。

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 に答える
0
while read line; do echo $(sed -n '$(echo $line)p' Datafile.txt); done < numbersfile.txt
于 2014-06-12T12:00:42.387 に答える