8

ファイルからの出力を解析したいという問題があり、できれば awk または sed を使用して、2 つのパターンの間で n 番目に出現するテキストを取得したい

category
1
s
t
done
category
2
n
d
done
category
3
r
d
done
category
4
t
h
done

この例で、category と done の間で 3 番目に出現するテキストを取得したいとします。基本的に、出力は次のようになります。

category
3
r
d
done
4

5 に答える 5

8

これはうまくいくかもしれません(GNU sed):

'sed -n '/category/{:a;N;/done/!ba;x;s/^/x/;/^x\{3\}$/{x;p;q};x}' file

オプションを使用して、自動印刷をオフにし-nます。categoryとの間の行をまとめますdone。ホールド スペースにカウンターを格納し、3 に達したらパターン スペースにコレクションを出力して終了します。

または awk を好む場合:

awk  '/^category/,/^done/{if(++m==1)n++;if(n==3)print;if(/^done/)m=0}'  file
于 2012-11-08T07:10:03.843 に答える
7

これをやってみてください:

 awk -v n=3 '/^category/{l++} (l==n){print}' file.txt

またはより不可解:

awk -v n=3 '/^category/{l++} l==n' file.txt

ファイルが大きい場合:

awk -v n=3 '/^category/{l++} l>n{exit} l==n' file.txt
于 2012-11-08T02:30:51.947 に答える
2

ファイルにヌル文字が含まれていない場合は、GNU sed. これにより、パターン範囲の3 番目のオカレンスが検出されます。ただし、これを簡単に変更して、任意のオカレンスを取得できます。

sed -n '/^category/ { x; s/^/\x0/; /^\x0\{3\}$/ { x; :a; p; /done/q; n; ba }; x }' file.txt

結果:

category
3
r
d
done

説明:

スイッチでデフォルトの印刷をオフにします-n。行頭の「カテゴリ」という単語に一致します。パターン スペースをホールド スペースと交換し、パターンの先頭にヌル文字を追加します。この例では、パターンに先行する 2 つのヌル文字が含まれている場合、ホールドスペースからパターンを引き出します。ここでループを作成し、最後のパターンが一致するまでパターン スペースの内容を出力します。この最後のパターンが見つかると、sed終了します。見つからない場合sedは、引き続き入力の次の行を読み取り、ループを続行します。

于 2012-11-08T04:00:31.117 に答える
1
awk -v tgt=3 '
/^category$/ { fnd=1; rec="" }

fnd {
   rec = rec $0 ORS
   if (/^done$/) {
      if (++cnt == tgt) {
         printf "%s",rec
         exit
      }
      fnd = 0
   }
}
' file
于 2012-11-08T13:20:58.900 に答える
0

GNU awk を使用すると、レコード セパレータを正規表現に設定できます。

<file awk 'NR==n+1 { print rt, $0 } { rt = RT }' RS='\\<category' ORS='' n=3

出力:

category 
3
r
d
done

RT一致したレコード区切りです。最初のレコードnは最初のRS.

編集

Ed のコメントによると、レコード間に他のデータがある場合、これは機能しません。

category
1
s
t
done
category
2
n
d
done

foo

category
3
r
d
done

bar
category
4
t
h
done

これを回避する 1 つの方法は、2 番目 (または最初) の awk で入力をクリーンアップすることです。

<file awk '/^category$/,/^done$/' |
  awk 'NR==n+1 { print rt, $0 } { rt = RT }' RS='\\<category' ORS='' n=3

出力:

category 
3
r
d
done

編集 2

Edがコメントで指摘したように、上記のメソッドは終了パターンを検索しません。これを行う1つの方法は、他の回答ではカバーされていませんが、次のとおりです( awk getlinegetlineにはいくつかの注意事項があることに注意してください):

<file awk '
  /^category$/ {
    v = $0
    while(!/^done$/) { 
      if(!getline) 
        exit
      v = v ORS $0
    }
    if(++nr == n) 
      print v
}' n=3

1 行で:

<file awk '/^category$/ { v = $0; while(!/^done$/) { if(!getline) exit; v = v ORS $0 } if(++nr == n)  print v }' n=3
于 2012-11-08T08:30:27.310 に答える