前の行に特定の単語が含まれている場合にのみ行を印刷します。

前の行に特定の単語が含まれている場合にのみ行を印刷します。

ホスト名とホストIPを含む次のファイルがあります(長いファイル、Linuxボックスあたり90〜100台のマシン)。

hosts.cluster.conf

  "href" : "http://localhost:8080/api/v1/hosts/worker02.sys87.com",
  "Hosts" : 
    "cluster_name" : "hdp",
    "host_name" : "worker02.sys87.com",
    "ip" : "23.67.32.65"


  "href" : "http://localhost:8080/api/v1/hosts/worker03.sys87.com",
  "Hosts" : 
    "cluster_name" : "hdp",
    "host_name" : "worker03.sys87.com",
    "ip" : "23.67.32.66"


  "href" : "http://localhost:8080/api/v1/hosts/worker04.sys87.com",
  "Hosts" : 
    "host_name" : "worker04.sys87.com",
    "ip" : "23.67.32.67"


  "href" : "http://localhost:8080/api/v1/hosts/worker05.sys87.com",
  "Hosts" : 
    "cluster_name" : "hdp",
    "host_name" : "worker05.sys87.com",
    "ip" : "23.67.32.68"

すべて印刷したいです。CPU名前の行に「が含まれている場合のみクラスタ名「言葉

期待されるパフォーマンス

"host_name" : "worker02.sys87.com",

"host_name" : "worker03.sys87.com",

"host_name" : "worker05.sys87.com",

答え1

sed '/host_name/!h;//!d;x;/cluster_name/!d;g' infile

host_name前のバッファと一致しないすべてのラインを保存hし、残りのdラインすべてを削除します。xバッファを変更し、パターン空間に対応する行がない場合はcluster_name削除します。それ以外の場合は、gバッファに保存して自動的に印刷します。元の行を返します。

答え2

努力する

 awk '/cluster_name/ {p=1 ; next ;} 
 /host_name/ && p { print ; }
 {p=0}' 

基本的にこれだけ覚えてくださいcluster_namehost_name見つかったが以前に見つからなかった場合はcluster_name印刷されません。

完全なawkコードは1行にすることができます。

答え3

短いawk解決策:

awk '/cluster_name/{ cl=NR }/host_name/ && NR-1==cl' hosts.cluster.conf
  • /cluster_name/{ cl=NR }-"cluster_name"レコード行数の取得
  • /host_name/- 出会いの"host_name"ラインで
  • NR-1==cl- 現在の"host_name"レコード番号がレコード番号の後に(としてマークされている)NRことを確認してください。"cluster_name"cl

出力:

"host_name" : "worker02.sys87.com",
"host_name" : "worker03.sys87.com",
"host_name" : "worker05.sys87.com",

最初の行に表示された場合は、host_name実際には疑わしいか、次のバージョンを使用してください。

awk '/cluster_name/{ cl=NR }/host_name/ && cl && NR-1==cl' hosts.cluster.conf

答え4

さて、ここまで来ましたsedawk今GNUを使う時間ですgrep

cat infile | grep --after-context 1 cluster_name | grep host_name

説明する

最初のコマンドは、cat処理のためにデータをパイプに読み込みます。この段落をソーステキストをに出力するコマンドで置き換えることができますstdout

2番目のコマンドは、「cluster_name」を含む行を見つけて、その行と次の行を印刷します。中間出力は次のとおりです。

"cluster_name" : "hdp",
"host_name" : "worker02.sys87.com",
--
"cluster_name" : "hdp",
"host_name" : "worker03.sys87.com",
--
"cluster_name" : "hdp",
"host_name" : "worker05.sys87.com",

最後の段落では、「host_name」を含む行の内容のみを印刷します。したがって、最終出力は次のようになります。

"host_name" : "worker02.sys87.com",
"host_name" : "worker03.sys87.com",
"host_name" : "worker05.sys87.com",

コメント

  1. grep誰もが「GNU grepを使用していることを確認する」というわけではなく、--before-context parameter.大丈夫でしょう。
  2. これがJSONのような言語であれば、jmespathまたはjq

関連情報