「--」で区切られたテキスト行(「段落」)を印刷するプログラムがあります。たとえば、印刷できます。
--
are you happy
--
I am hungry
are you
--
are(you hungry
too
私はこれを別のプログラム(おそらくsed?)にパイプし、与えられた単語(例えば「are」)で始まる段落だけを返したいと思います。したがって、上記の場合、「are」で始まる段落を取得すると、次のような結果が得られます。
--
are you happy
--
are(you hungry
too
プログラムは非常に多数の「段落」を印刷しますが、小さな部分だけが一致すると予想しています。これがプログラムの出力をストリーミング方式でフィルタリングできるようにしたい理由です(すべてを1つで書くのを避けるため)。大きなファイルをフィルタリングしてからフィルタリングしてください。
ベストアンサー1
AWK
GNU awkまたはmawkの使用:
$ awk '$1~"^"word{printf("--\n%s",$0)}' word='are' RS='--\n' infile
--
are you happy
--
are(you hungry
too
これは、変数の単語をレコードの先頭で一致させる単語に設定し、レコード区切り記号(RS)を「--」に設定し、新しい行を追加します\n
。次に、()に一致する単語で始まるレコードにフォーマットされた$1~"^"word
レコードを印刷します。形式は、「--」で始まり、見つかった正確なレコードを含む新しい行を持つことです。
グレブ
(GNUオプション-z
)grepを使用してください。
grep -Pz -- '--\nare(?:[^\n]*\n)+?(?=--|\Z)' infile
grep -Pz -- '(?s)--\nare.*?(?=\n--|\Z)\n' infile
grep -Pz -- '(?s)--\nare(?:(?!\n--).)*\n' infile
説明次の説明では、PCREオプションを(?x)
使用して、実際の(動作する)正規表現と共に(大きな)説明コメント(およびスペース)をインラインで追加します。コメント(およびほとんどのスペース)(次の改行まで)が削除された場合、結果の文字列はまだ同じ正規表現です。これにより、作業コードの正規表現の詳細な説明が可能になります。これにより、コードのメンテナンスが容易になります。
オプション1正規表現 (?x)--\nare(?:[^\n]*\n)+?(?=--|\Z)
(?x) # match the remainder of the pattern with the following
# effective flags: x
# x modifier: extended. Spaces and text after a #
# in the pattern are ignored
-- # matches the characters -- literally (case sensitive)
\n # matches a line-feed (newline) character (ASCII 10)
are # matches the characters are literally (case sensitive)
(?: # Non-Capturing Group (?:[^\n]*\n)+?
[^\n] # matches non-newline characters
* # Quantifier — Matches between zero and unlimited times, as
# many times as possible, giving back as needed (greedy)
\n # matches a line-feed (newline) character (ASCII 10)
) # Close the Non-Capturing Group
+? # Quantifier — Matches between one and unlimited times, as
# few times as possible, expanding as needed (lazy)
# A repeated capturing group will only capture the last iteration.
# Put a capturing group around the repeated group to capture all
# iterations or use a non-capturing group instead if you're not
# interested in the data
(?= # Positive Lookahead (?=--|\Z)
# Assert that the Regex below matches
# 1st Alternative --
-- # matches the characters -- literally (case sensitive)
| # 2nd Alternative \Z
\Z # \Z asserts position at the end of the string, or before
# the line terminator right at the end of the
# string (if any)
) # Closing the lookahead.
オプション2正規表現 (?sx)--\nare.*?(?=\n--|\Z)\n
(?sx) # match the remainder of the pattern with the following eff. flags: sx
# s modifier: single line. Dot matches newline characters
# x modifier: extended. Spaces and text after a # in
# the pattern are ignored
-- # matches the characters -- literally (case sensitive)
\n # matches a line-feed (newline) character (ASCII 10)
are # matches the characters are literally (case sensitive)
.*? # matches any character
# Quantifier — Matches between zero and unlimited times,
# as few times as possible, expanding as needed (lazy).
(?= # Positive Lookahead (?=\n--|\Z)
# Assert that the Regex below matches
# 1st Alternative \n--
\n # matches a line-feed (newline) character (ASCII 10)
-- # matches the characters -- literally.
| # 2nd Alternative \Z
\Z # \Z asserts position at the end of the string, or
# before the line terminator right at
# the end of the string (if any)
) # Close the lookahead parenthesis.
\n # matches a line-feed (newline) character (ASCII 10)
オプション3正規表現 (?xs)--\nare(?:(?!\n--).)*\n
(?xs) # match the remainder of the pattern with the following eff. flags: xs
# modifier x : extended. Spaces and text after a # in are ignored
# modifier s : single line. Dot matches newline characters
-- # matches the characters -- literally (case sensitive)
\n # matches a line-feed (newline) character (ASCII 10)
are # matches the characters are literally (case sensitive)
(?: # Non-capturing group (?:(?!\n--).)
(?! # Negative Lookahead (?!\n--)
# Assert that the Regex below does not match
\n # matches a line-feed (newline) character (ASCII 10)
-- # matches the characters -- literally
) # Close Negative lookahead
. # matches any character
) # Close the Non-Capturing group.
* # Quantifier — Matches between zero and unlimited times, as many
# times as possible, giving back as needed (greedy)
\n # matches a line-feed (newline) character (ASCII 10)
sed
$ sed -nEe 'bend
:start ;N;/^--\nare/!b
:loop ;/^--$/!{p;n;bloop}
:end ;/^--$/bstart' infile