中括弧内のテキストを一致させ、中括弧全体を印刷する正規表現

中括弧内のテキストを一致させ、中括弧全体を印刷する正規表現

次の構成ファイルがあります。

define host{
        host_name xxxxxxxx1748
        use windows-server
        alias Comet
        hostgroups +bu-automotiveprd,screen-automotiveprd2
        address XXX.XXX.XXX.XXX
}


define host{
        host_name yyyyyyyyy991
        use aix-server
        alias
        hostgroups +bu-automotiveprd,screen-automotiveprd2
        address YYY.YYY.YYY.YYY
}

検索したいCPU名、一致するものがある場合、出力は次のようになります。

yyyyyyyyy991はい - ホストを検索したいとしましょう。

その後、出力は次のようになります。

define host{
        host_name yyyyyyyyy991
        use aix-server
        alias
        hostgroups +bu-automotiveprd,screen-automotiveprd2
        address YYY.YYY.YYY.YYY
}

答え1

この試み、

perl -0777 -ne '/([^\n]*{[^}]*(yyyyyyyyy991)[^}]*})/ && print "$1\n"' file

説明する:

  • perl -0777Perlを実行し、ファイル全体を1行に読み込みます。
  • -ne各行(n)に対してe次の()操作を実行します。
  • /(pattern)/ && print "$1\n"正規表現パターンを一致させ、それを最初の一致グループ($1)として追加してから印刷します。

モデル:

  • [^\n]*{ ... }「{」から次の「}」までを含む行の先頭から何でも一致します。
  • そして...存在[^}]*(yyyyyyyyy991)[^}]*
    • そうでないすべての文字と一致します。}
    • どこかに含める必要がありますyyyyyyyyy991

答え2

サポートしている場合は、grepこの-zオプションを使用してファイル全体を食べさせることができます。

$ grep -ozE 'define[^}]*host_name yyyyyyyyy991.+?}.' file
define host{
        host_name yyyyyyyyy991
        use aix-server
        alias
        hostgroups +bu-automotiveprd,screen-automotiveprd2
        address YYY.YYY.YYY.YYY
}

使用されるオプションは次のとおりです(GNUページgrepから):mangrep

  -z, --null-data
          Treat  input  and output data as sequences of lines, each terminated by a
          zero byte (the ASCII NUL character) instead of a newline.  Like the -Z or
          --null  option,  this  option  can  be used with commands like sort -z to
          process arbitrary file names.
  -o, --only-matching
          Print only the matched (non-empty) parts of a matching  line,  with  each
          such part on a separate output line.
  -E, --extended-regexp
          Interpret PATTERN as an extended regular expression (ERE, see below).

正規表現は、単語defineの後にゼロ個以上の非}文字([^}]*)が続く単語を検索し、最初の()と改行文字(最後の文字)に一致する次の文字host_name yyyyyyyyy991までのすべての項目を検索します。}.+?.


しかし、個人的に私はPerlの短絡モードを使って次のことをします。

$ perl -00 -ne 'print if /yyyyyyyyy991/' file
define host{
        host_name yyyyyyyyy991
        use aix-server
        alias
        hostgroups +bu-automotiveprd,screen-automotiveprd2
        address YYY.YYY.YYY.YYY
}

入力ファイルが段落として読み取られるため、各レコードは1行ではなく段落(2つの連続した文字として定義されている-00)であることを示します。これは「各入力レコードを読み、与えられたスクリプトをここに適用する」という意味です。スクリプト自体は、目的のパターンに一致するすべてのレコードを単に印刷します。perl\n-ne-e

答え3

構成ファイルの名前が config.dat で、次のものがあるとします。基準滞在。つまり、yyyyyyyyy991の前には1行だけ、その後には5行しかありません。これにより、このコマンドは目的の出力を取得するのに役立ちます。

grep -B 1 -A 5 "yyyyyyyyy991" config.dat

define host{
        host_name yyyyyyyyy991
        use aix-server
        alias
        hostgroups +bu-automotiveprd,screen-automotiveprd2
        address YYY.YYY.YYY.YYY
}

~からgrep男性:

Context control flage:
  -B, --before-context=NUM  print NUM lines of leading context
  -A, --after-context=NUM   print NUM lines of trailing context

config.dat ファイルが別のソリューションの場合標準ではないこれは、キーワード "yyyyyyyyy991"がすべてのセクションで同じパターンに従わないことを意味するため、awk次のようにしたいことができます。

 awk -v RS='' '/host_name yyyyyyyyy991/' config.dat

RS =は、入力レコード区切り文字を改行文字から空白行に変更します。レコードのフィールドに/ host_name yyyyyyyyy991 /が含まれている場合は、レコードを印刷します。

POSIXによると

RSが空の場合、レコードは1つ以上の空行シーケンスに分けられます。先頭または末尾の空行は、入力の先頭または末尾に空のレコードにしてはいけません。aは、FS Whatに関係なく常にフィールド区切り文字でなければなりません。値です。

出力区切り文字は依然として単一の改行文字であるため、出力段落は区別されません。出力段落の間に空白行があることを確認するには、出力レコード区切り文字を2つの改行に設定します。

答え4

使用sed:

sed 'H;/^define host{$/h;/^}/{g;/host_name yyyyyyyyy991\n/p};d' file

ステップバイステップ:

H                  # append line to hold space
/^define host{$/h  # start of entry: copy to hold space (overwrites previous content)
/^}/{              # end of entry:
        g                            # retrieve whole entry from hold space
        /host_name yyyyyyyyy991\n/p  # if host matched, display the whole entry
}
d                  # no other output

関連情報