web-dev-qa-db-ja.com

bashスクリプトでawkを使用して複数行のレコードを処理するにはどうすればよいですか?

example.txtは以下です

Restaurant: McDonalds 
City: Miami
State: Florida
Address: 123 Biscayne Blvd
Phone: 911

Restaurant: 5 guys
City: Atlanta
State: Georgia
Address: 123 Peachtree Rd
Phone: 911

Restaurant: KFC
City: NYC
State: NY
Address: 123 Madison Square
Phone: 911

私はbashスクリプトを使用しており、上記のファイルから名前でレストランを検索したいと言うことができます。ユーザー名にレストラン名を入力すると、そのレストランに関する情報(5行)が出力されます。

awk '/McDonalds/> /KFC/' example.txt

上記のコード行は、パターン "McDonalds"および "KFC"に一致する行全体を印刷しますが、テキストファイルの1行目のみを印刷し、そのレストランに関する残りの情報は印刷しないことを知っています。レストラン名のユーザー入力のみからすべての情報(5行)を印刷するように指示するにはどうすればよいですか?

13
Selena Gomez

Awkを使用すると、recordセパレータを変更できます。デフォルトでは改行であるため、ファイルの各行はレコードです。 RS変数を空の文字列に設定すると、awkはレコードが空白行で区切られていると見なします。

awk -v name="KFC" -v RS="" '$0 ~ "Restaurant: " name' example.txt
11
glenn jackman

sedを使用:

$ sed -n '/KFC/,/^$/p' file
Restaurant: KFC
City: NYC
State: NY
Address: 123 Madison Square
Phone: 911

$ sed -n '/McDo/,/^$/p' file
Restaurant: McDonalds
City: Miami
State: Florida
Address: 123 Biscayne Blvd
Phone: 911

説明

これは基本的なsed関数です。 SED ONE-LINE SCRIPTS FOR SED を参照できます

# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p'             # case sensitive
3
BMW
$ awk '$2=="KFC" {print; for(i=1; i<=4; i++) { getline; print}}' example.txt

Restaurant: KFC
City: NYC
State: NY
Address: 123 Madison Square
Phone: 911

上記のコマンドは、forループに入力されたため、連続する4行と現在の行を取得して出力します。検索パターン$2=="KFC"は、複数の行から特定の行を取得するのに役立ちます。

1
Avinash Raj

別の可能な解決策:

awk 'BEGIN{FS="\n";RS="\n\n"}{if($1=="KFC")print $0}' example.txt
0
Faisal

必要な名前を含む行からWord Phoneを含む最後の行まで印刷するだけで十分です(もちろん、すべてのエントリが同じパターンに従い、常に終了レコードとしてPhoneを持つと仮定します)

$> awk '/5 guys/,/Phone/' restaurants.txt                                     
Restaurant: 5 guys
City: Atlanta
State: Georgia
Address: 123 Peachtree Rd
Phone: 911
$> awk '/McDonalds/,/Phone/' restaurants.txt                                  
Restaurant: McDonalds 
City: Miami
State: Florida
Address: 123 Biscayne Blvd
Phone: 911

少し複雑にしたい場合は、次のように、一致の後に正確に5行を印刷できます。

awk '/McDonalds/{stop=NR+5}; NR<=stop ' restaurants.txt                    

Restaurant: McDonalds 
City: Miami
State: Florida
Address: 123 Biscayne Blvd
Phone: 911

stop変数は設定されないため、NR<=stop部分が実際に変数を設定するまで、/McDonalds/{stop=NR+5;}は何も出力しません。これは、一致するものが見つかると発生します。

0