2つのパターン間の線抽出(2つのパターンを含む)

2つのパターン間の線抽出(2つのパターンを含む)

次のデータ構造を持つファイルがあります

1, p1, p2, p3, p4, p5, p6, p7
2, p9, p10,,
2, q1, q2, q3, q4, q5, q6, q7
2, q9, q10,,
2, r1, r2, r3, r4, r5, r6, r7
2, r9, r10,,
1, s1, s2, s3, s4, s5, s6, s7
2, s9, s10,,
...

私は1で始まり、で終わるすべての行を取得したいと思います。

1, p1, p2, p3, p4, p5, p6, p7
2, p9, p10,,
1, s1, s2, s3, s4, s5, s6, s7
2, s9, s10,,

可能であれば、

1, p1, p2, p3, p4, p5, p6, p7, 2, p9, p10,,
1, s1, s2, s3, s4, s5, s6, s7, 2, s9, s10,,

sedまたはawkを使用してこれをどのように実行できますか?

答え1

sed以下は、最後に発生した行の後に一連の行をリンクするソリューションです。,,$^1

sed -e '/^1/{x;s/\n/ /gp;d' -e '};/,,$/H;$G;D
' <<\IN                                                                          
1, p1, p2, p3, p4, p5, p6, p7
2, p9, p10,,
2, q1, q2, q3, q4, q5, q6, q7
2, q9, q10,,
2, r1, r2, r3, r4, r5, r6, r7
2, r9, r10,,
1, s1, s2, s3, s4, s5, s6, s7
2, s9, s10,,
IN

aで始まる行の既存のスペースとパターンスペースを変更しx、置き換えが成功した場合は、既存のスペースの前の内容のみを印刷します。で終わる行には、ewline文字の後に前のスペースが追加され、ewline文字が最初に表示されるまですべての行が削除されます。最後の行では、前のスペースはewlineの後のパターンスペースに追加されます。したがって、削除されると、前のスペースに含まれていた内容のみを含むスクリプトの上部で行ループを再起動し、必要に応じて印刷します。h^1s///ph,,$H\nD\n$H\nDH

出力:

1, p1, p2, p3, p4, p5, p6, p7 2, p9, p10,, 2, q9, q10,, 2, r9, r10,,
1, s1, s2, s3, s4, s5, s6, s7 2, s9, s10,,

一方、後でこれが発生しないようにするには、/,,$/次のようにします。

sed -e '/^1/{x;y/\n/ /;s/,,.*/,,/p;d' -e '};/,,$/H;$G;D'

同じ入力が印刷されると、次のようになります。

1, p1, p2, p3, p4, p5, p6, p7 2, p9, p10,,
1, s1, s2, s3, s4, s5, s6, s7 2, s9, s10,,

ただし、一致が/,,$/すぐに続かなくても/^1/行は印刷されます。入力ですぐに連続するペアのみが必要な場合は、次のこともできます。

sed -n '/^1/!d;$p;N;/\n1/P;/,,$/s/\n/ /p;D'

仕組みは次のとおりです。

  • まずd、出力から!起動しないすべてを削除します。/^1/
    • これNには、紹介が終わらない行が含まれます/,,$/
  • これが最後の入力行の場合、次のコマンドはスクリプトを終了するため、$パターンスペースがここに印刷されます。p
  • /^1/一致すると、Nパターンスペースの\newline文字にext入力行を追加します。
  • 追加行の場合返品aで始まると、前の項目が印刷されます /\n1/P
    • P\nパターン空間で最初に現れる電子ラインだけが印刷されます。
  • 追加の入力行をインポートした後にNパターンスペースが$matchで終わる場合は、挿入されたewline文字を空白文字に/,,$/置き換えて結果を印刷します。s///\np
  • パターン空間はいつも D最初に表示されるewline文字まで削除します\n
    • ...したがって、N外部入力行が一致しない場合は、/,,$/スクリプトの最初の行に戻ります。このとき一致する内容がないと完全に削除さ^1れますd
    • .../,,$/この時点でewlineが完全に削除されたため、ここのプロセスからも完全に削除されました。\n

これが意味するのは、/^1/線が互いに接続されている場合は印刷され続け、線が,,$aで終わらないと^1印刷されないことです。

答え2

最初のクエリに関しては、-esedで式の組み合わせを使用できます。

~$ sed -n -e '/^1/p' -e '/,,$/p' f
1, p1, p2, p3, p4, p5, p6, p7
2, p9, p10,,
2, p9, p10,,
2, p9, p10,,
1, p1, p2, p3, p4, p5, p6, p7
2, p9, p10,,

重複したくない場合:

~$ sed -n -e '/^1/p' -e '/,,$/p' f | uniq
1, p1, p2, p3, p4, p5, p6, p7
2, p9, p10,,
1, p1, p2, p3, p4, p5, p6, p7
2, p9, p10,,

awkを使用して正規表現を次のように組み合わせます;

~$ awk '/^1/;/,,$/' f
1, p1, p2, p3, p4, p5, p6, p7
2, p9, p10,,
2, p9, p10,,
2, p9, p10,,
1, p1, p2, p3, p4, p5, p6, p7
2, p9, p10,,

答え3

ORS希望の形式で出力するように条件付きで設定できます。

awk '/^1/,/,,$/{ORS = /^1/? ", ": "\n"; print}' file
1, p1, p2, p3, p4, p5, p6, p7, 2, p9, p10,,
1, p1, p2, p3, p4, p5, p6, p7, 2, p9, p10,,

関連情報