パターンに一致するすべての行を検索し、その上の行だけを印刷します。

パターンに一致するすべての行を検索し、その上の行だけを印刷します。

文字列を見つけて、その上の行を印刷する必要があります。

ケース 1: 同じ行に複数の一致するパターンがありません。

つまり、以下を含むファイルを考えてみましょう。

$cat > para
returns between the paragaraphs
italic or bold    
quotes by placing
italic

ここでイタリック体を探し、以下のように出力を得る必要があります。

段落の間に戻る
見積を出して

どのようにそのような結果を得ることができますか?

答え1

一致するテキストの文脈では、「パターン」という単語は非常にあいまいなので、使用しないでください。一致を参照する項目のうち、少なくとも「文字列」または「正規表現」と「部分」または「完全」を常に使用してください。バラよりhttps://stackoverflow.com/q/65621325/1745001より多くの情報を知りたいです。

あなたの質問はあなたが望む一致の種類を知ることができないので、次は公開されたサンプル入力に基づいて公開された期待される出力を生成するいくつかの例です。できます。 :

部分行正規表現の一致:

$ awk '/italic/{print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

部分行文字列の一致:

$ awk 'index($0,"italic"){print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

部分フィールド正規表現の一致:

$ awk '{for (i=1; i<=NF; i++) if ($i ~ /italic/) print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

部分フィールド文字列の一致:

$ awk '{for (i=1; i<=NF; i++) if (index($i,"italic")) print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

全フィールド正規表現の一致

a)単語の境界にGNU awkを使用):

$ awk '/\<italic\>/{print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

b) awk を使用します。

$ awk '/(^|[[:space:]])italic([[:space:]]|$)/{print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

完全なフィールド文字列の一致:

a) ループを使用します。

$ awk '{for (i=1; i<=NF; i++) if ($i == "italic") print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

b)ループと正規表現のサポートなし:

$ awk 's=index($i,"italic") && (substr($0,s-1,1) ~ /^|[[:space:]]/) && (substr($0,s+length("italic"),1) ~ /[[:space:]]|$/){print p} {p=$0}' file
returns between the paragaraphs
quotes by placing

上記のすべての項目は、公開された入力例に基づいて予想される出力を生成し、文字列と正規表現、正確な一致と部分一致の要件によって入力が異なる場合、上記のすべての項目は失敗します。

答え2

パターンが連続した行に表示されない場合は、簡単に実行できます。

sed '$!N;/.*\n.*PATTERN.*/P;D' infile

私は持っていますここで説明されていますNループがP機能Dします。違いは、パターン空間の最初の行は、2番目の行が一致する場合にのみ印刷され、そうでなければ削除されることです。


パターンが連続した行に表示される場合、上記の解決策は一致する行を印刷します(他の一致する行が次に来る場合)。
連続一致を無視するには、一致がない場合にパターンスペースの最初の行のみを印刷する2番目の条件を追加します。

sed '$!N;/.*\n.*PATTERN.*/{/.*PATTERN.*\n.*/!P;};D' infile

別のアプローチは、保持バッファを使用することである。
連続一致を無視するには:

sed '/PATTERN/!{              # if line doesn't match PATTERN
h                             # copy pattern space content over the hold buffer
d                             # delete pattern space
}
//{                           # if line matches PATTERN
x                             # exchange pattern space with hold space
//d                           # if line matches PATTERN delete it
}' infile

または一行で

sed '/PATTERN/!{h;d;};//{x;//d;}' infile

連続一致を無視しない場合は、次のようにします。

sed '/PATTERN/!{              # if line doesn't match PATTERN
h                             # copy pattern space content over the hold buffer
d                             # delete pattern space
}
//x                           # if line matches PATTERN exchange buffers
' infile 

または一行で

sed '/PATTERN/!{h;d;};//x' infile

ただし、予約済みバッファを使用する両方のソリューションは、ファイルの最初の行が一致すると空白行が前に印刷されることに注意してください。これが問題の場合は、1d最初の確認後に//例えば
sed '/PATTERN/!{h;d;};//{1d;x;//d;}'sedを追加します。'/PATTERN/!{h;d;};//{1d;x;}'

答え3

使用grep、その後sed:

grep --no-group-separator -B 1 "italic" <yourfilename> | sed -n 1~2p`

説明する:

grep手動:

-B num
--before-context=num
Print num lines of leading context before matching lines

--no-group-separator
When -A, -B or -C are in use, do not print a separator between groups of lines.

sed:

2つの行のうち最初の行を選択します。 sed -n 1〜5pと入力して、5つのうち最初のものを選択することもできます。

関連情報