次のパターンまでこのパターンの後の2行ごとにマージ

次のパターンまでこのパターンの後の2行ごとにマージ

ファイル.txt

String1?
word1
word2
word3
word4

String2?
word5
word6
word7
word8

希望の出力:

String1?
word1 | word2
word3 | word4

String2?
word5 | word6
word7 | word8

私が試した唯一のパターンはlineです/?$/

sed '/\?$/{n;:l N;/\?$/b; :a; N; $!b a; s/\n\s\{1,\}/ | /g; bl}'

しかし、それはうまくいきませんでした。私の現在の作業ソリューション:

sed '/\?$/{:a;N;/\n....-..-.. /!s/\n/ - /;ta;P;D}' | sed 's/^[- ]*//g;s/[ -]*$//g'

...しかし、回避策であり、非常に遅い速度です。パイプなしのシングルライナーとクイックソリューションで役立つ人はいますか?

パターンのように空白行がなく、,$\|^$^$が存在せず、?$を含む他の行がある場合は、どのように?$から貪欲でない最初の?$パターンまでバッファを保存し、最後のAllを除いて印刷できますか? ? 1行だけ検索し、最後の行を次のパターンバッファとマージして検索しますか?

答え1

GNU sed専用です。
ブロックのすべての行に正確に2つの列がある場合(あなたの場合):

sed '/?$\|^$/b;N;s/\n/ | /' File.txt

奇妙なコンテンツが可能な場合(一般的な方法):

sed '/?$\|^$/b;N;/\n$/!s/\n/ | /' File.txt

答え2

入力例に示すように、入力が空白行で区切られたテキストブロックであると仮定した場合は、すべてのUnixシステムのすべてのシェルでawkを使用してください。

$ awk -v RS= -F'\n' -v OFS=' | ' '{print $1; for (i=2; i<NF; i+=2) print $i, $(i+1); print ""}' file
String1?
word1 | word2
word3 | word4

String2?
word5 | word6
word7 | word8

答え3

$ sed '/?$/,/^$/ { //b; N; y/\n/|/; }' file
String1?
word1|word2
word3|word4

String2?
word5|word6
word7|word8

行範囲の場合、末尾にaがある行/?$/,/^$/から空行まで:?

  • 現在の行が範囲の最初または最後の行である場合は、何もしません(//b; "(このループで)最後に一致した正規表現が一致すると、スクリプトの末尾に分岐します。")。
  • それ以外の場合は、次の入力行をバッファ(N)に追加し、挿入された改行文字を1文字に置き換えます|。パイプの周りに間隔を置くには、代わりにs/\n/ | /を使用しますy/\n/|/

POSIX方式:

sed -e '/?$/,/^$/ { //b' -e N -e 'y/\n/|/' -e '}' file

または、ここで提供されている別のスクリプトファイルを使用してください。

sed -f /dev/stdin file <<'END_SED'
/?$/,/^$/ {
    // b
    N
    y/\n/|/
}
END_SED

のようなものawk

awk -v OFS='|' '
    /\?$/,length == 0 {
        if ( !/\?$/ && length != 0) {
            getline n
            print $0, n
        } else print
    }' file

/^$/出力でパイプ区切り文字の周りにスペースが必要な場合は、上記のコードを代わりにlength == 0使用することもできますOFS=' | 'OFS='|'

答え4

Perlショートモード(-00)では、次のことができます。

perl -aF'\n' -nls -00e '
  print shift @F;
  print splice(@F,0,2) while @F>1;
  print @F if !eof;
' -- -,=" | " file

正規表現の作成を簡素化するには、拡張正規表現モード(-E)でGNU sedを使用します。

sed -E '
  /./{H;$!d;}
  x;$!G;s///
  s/([^\n]*\n){2}/&|/g
  s/\n\|/ | /g
' file

関連情報