web-dev-qa-db-ja.com

一致がn回出現した後の行を出力する

次のファイルの4598行目を表示しようとしています。事実上、一致のn番目の出現後に行を表示したい。この場合、3回目の<Car>の後の行です。これについてどうすればいいですか?

<Car>
10456
</Car>
<Car>
70192
</Car>
<Car>
4598
</Car>
8
DJ180
awk -v n=3 '/<Car>/ && !--n {getline; print; exit}'

または:

awk '/<Car>/ && ++n == 3 {getline; print; exit}'

検索パターンを変数として渡すには:

var='<car>'
PATTERN="$var" awk -v n=3 '
  $0 ~ ENVIRON["PATTERN"] && ++n == 3 {getline; print; exit}'

ここで、-vの代わりにENVIRONを使用すると、-vはバックスラッシュエスケープシーケンスを展開し、バックスラッシュは正規表現でよく見られます(-vで二重にする必要があります)。

GNU awk 4.2以降では、変数を strong typed regexps として割り当てることができます。 POSIXモードが有効になっていない限り(たとえば、$POSIXLY_CORRECT環境変数を使用して)、次のことができます。

# GNU awk 4.2 or above only, when not in POSIX mode
gawk -v n=3 -v pattern="@/$var/" '
  $0 ~ pattern && ++n == 3 {getline; print; exit}'
10

これがPerlのものです:

Perl -ne 'print && exit if $c==3; $c++ if /<Car>/;' file 

GNU grepを使用すると、次のようにその出力を解析することもできます。

grep -A 1 -m 3 '<Car>' file | tail -n 1

man grepから:

-A NUM, --after-context=NUM
          Print NUM lines of trailing context after matching lines.  
          Places a line containing a group separator (--) between 
          contiguous  groups  of  matches.          
-m NUM, --max-count=NUM
          Stop reading a file after NUM matching lines.  
4
terdon

GNU awk できるよ:

gawk -v RS='</Car>' 'NR==3 && $0=$2' inputFile
3
jaypal singh

sedの別の方法を次に示します。

sed -n '/<Car>/{x;/.\{2\}/{x;$!{n;p};q};s/.*/&./;x}' infile

これは、カウントにホールドスペースを使用しています。
<Car> it e xchangesに一致する行に遭遇するたびに、ホールドバッファー内に文字が正確にN-1出現するかどうかを確認します。チェックが成功した場合、e xchangesが再度実行され、最後の行にない場合は、next行を取得し、printsパターンスペースを取得してから、quits 。それ以外の場合は、別の.文字を保持スペースに追加し、e xchangesを戻します。

1
don_crissti

簡単なコマンドラインソリューションを次に示します。

grep -F -A1 '<Car>' filename | grep -E -v '<Car>|--' | tail -n +3 |head -n +1

tailの後に+3の値を変更すると、任意のn番目の行を指定できます。

0
bsd