一致するパターン間の行を列に変換するBashスクリプト

一致するパターン間の行を列に変換するBashスクリプト

私の入力ファイルは次のとおりです。

START
line1
line2
line3
END
START
line11
line22
line33
END

私のスクリプトは次のように出力したいと思います。

START line1 line2 line3 END
START line11 line22 line33 END

助けてください。

答え1

使用awk:

$ awk '{printf "%s", $0 (($0 == "END") ? ORS : OFS)}'

STARTから まで行を書くには、END次のようにします。

$ awk '($0 =]"START"),($0 == "END"){printf "%s%s",$0, ($0=="END" ? ORS : OFS)}'

それ以外の場合は、次のコマンドを使用できますSTARTEND

$ awk '($0 == "START"){a="";} {a = a $0 (($0 == "END") ? "" : OFS)}  ($0 == "END"){print a}'

答え2

複数文字にはGNU awkを使用し、RSRTの例に示すように、データに常に完全でネストされず、重複しないSTART-ENDブロックがあるとします。

$ awk -v RS='\nEND\n' -F'\n' '{$0=$0 RT; $1=$1} 1' file
START line1 line2 line3 END
START line11 line22 line33 END

START-ENDブロックの外側に行を追加できる場合は、代わりに次のようにします。

$ awk -v RS='\nEND\n' -F'\n' 'RT{$0=gensub(/.*\n(START\n)/,"\\1",1) RT; $1=$1; print}' file
START line1 line2 line3 END
START line11 line22 line33 END

または awk を使用してください。

$ awk '
    $0 == "START" { f=1; rec=$0; next }
    f { rec=rec OFS $0; if ( $0 == "END" ) { print rec; f=0 } }
' file
START line1 line2 line3 END
START line11 line22 line33 END

入れ子になった、重なっている、または不完全なSTART-ENDブロックがあり、上記で必要に応じて機能しない場合は、これらの要件を表示するように質問を編集する必要があります。

答え3

使用sed:

$ sed -n -e '/^START$/ { h; d; }' -e H -e '/^END$/ { g; y/\n/ /; p; }' file
START line1 line2 line3 END
START line11 line22 line33 END

スクリプトsedはコメントとともに見事に印刷されます。

# Save each "START" line in the hold space and skip to the next line.
/^START$/ {
    h
    d
}

# Append all non-"START" lines to the hold space.
H

# On an "END" line, get the hold space, convert newlines to spaces, and print.
/^END$/ {
    g
    y/\n/ /
    p
}

これは、「START」行と「END」行の範囲が重複せず、「END」と「START」の間に追加データがないと仮定する。

答え4

使用幸せ(以前のPerl_6)

ENDあるレコードと次のレコードの間の中間行(たとえば、および間)を削除するには START

~$ raku -ne 'S/ <!after END> $/ / andthen do if /^START/ fff s/^END$/END\n/ {.print};'  file

または:

~$ raku -ne 'S/ <!after END> $/ / andthen print ($_ if /^START/ fff s/^END$/END\n/) ;'  file

上記はRakuプログラミング言語でコーディングされた答えです。つまり、-neコマンドラインフラグは、自動印刷なしで入力ファイルでコードを1行ずつ実行するために使用されます。単語で終わらない各行にS///「big-S」置換演算子を使用し(否定的な振り返り)、スペースを追加します。この手順を使用すると、間にスペースを含む行を簡単にリンクできます(注:@Kusalanandaがコメントに投稿したものと同様の回答を得るために使用されます)。<!after END> $END\t

引き続き$_テーマ変数の再読み込みを使用してくださいandthen。 Rakuのsedに似た/START/ fff /STOP/「トリプルf」トリガ演算子を使用して、目的のセンチネルライン間のラインをキャプチャできます。書式トリックでは、実際に同じトリガー演算子のセンチネル行をs/^END$/END\n/置き換えて、その後に改行を追加できます。ENDfff\nEND

最後に、出力は、print独自の改行文字を追加せずに上記の空白/改行形式を保持するRakuの単純な演算子を介して行われます。

入力例:

START
line1
line2
line3
END
test
START
line11
line22
line33
END

出力例(中央の行を削除):

START line1 line2 line3 END
START line11 line22 line33 END

さて、どうすれば中間線を守ることができますか?簡単です。fffRakuの「whatever-star」を使用してすべての出発線を許可するようにトリガー演算子を変更するだけです。*以下を参照してください。

~$ raku -ne 'S/ <!after END> $/ / andthen do if * fff s/^END$/END\n/ {.print};'  file
START line1 line2 line3 END
test START line11 line22 line33 END

#OR

~$ raku -ne 'S/ <!after END> $/ / andthen print ($_ if * fff s/^END$/END\n/);'  file
START line1 line2 line3 END
test START line11 line22 line33 END

https://docs.raku.org/syntax/S%2F%2F%2F%20Non-destructive%20replacement
https://docs.raku.org/routine/fff
https://docs.raku.org/routine/andthen
https://raku.org

関連情報