ファイル.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