行ブロックが空の行に分割され、行を列に変換する必要があるこのような入力があります。
入力する
HEAD1
IF
FI
GH
HEAD2
PU
GT
HEAD3
FG
DF
YT
GU
次のように印刷する必要があります。
HEAD1 IF FI GH
HEAD2 PU GT
HEAD3 FG DF YT GU
答え1
$ awk -v RS='' '{ $1 = $1; print }' file
HEAD1 IF FI GH
HEAD2 PU GT
HEAD3 FG DF YT GU
RS
入力レコード区切り文字がデフォルトの改行文字ではなく空白の場合、awk
入力は入力に表示される2つ以上の連続する改行に基づいてレコードに分割されます。つまり、1 つ以上の空行がレコードの終わりを示すものとして扱われます。これをしばしばawk
「短絡モード」と呼びます。
その後、コードは最初のフィールドを自分自身に設定します。これはランダムな操作のように見えるかもしれませんが、これはawk
現在の出力レコードを書き換えます。ORS
(出力レコード区切り文字)と(出力フィールド区切り文字)のデフォルト値が使用されるため、OFS
(それぞれ改行と空白)レコードが印刷されると、すべてのフィールドは間にスペースがあり、改行で終わる1行に印刷されます。 。
値を変更して、別の文字列または文字で区切られたフィールドを取得できますOFS
。
$ awk -v RS='' -v OFS='\t' '{ $1 = $1; print }' file
HEAD1 IF FI GH
HEAD2 PU GT
HEAD3 FG DF YT GU
$ awk -v RS='' -v OFS=',' '{ $1 = $1; print }' file
HEAD1,IF,FI,GH
HEAD2,PU,GT
HEAD3,FG,DF,YT,GU
$ awk -v RS='' -v OFS='::' '{ $1 = $1; print }' file
HEAD1::IF::FI::GH
HEAD2::PU::GT
HEAD3::FG::DF::YT::GU
このコードは、無条件のデフォルトジョブを呼び出して、後続のために現在のレコードが印刷されるようにawk
短縮できます。これは現在のレコードを無条件に印刷する非常に一般的な方法です。{ $1 = $1 }; 1
1
代わりに使用してくださいsed
:
$ sed -e '/./ { H; $!d; }' -e 'x; y/\n/ /; s/.//' file
HEAD1 IF FI GH
HEAD2 PU GT
HEAD3 FG DF YT GU
H
行に内容が含まれている場合は、現在の行を予約済みスペースに追加します。改行を区切って予約済みスペースに行を追加します。これが入力の最後の行でない場合、パターン空間は廃棄され、d
次の入力行からすぐに開始されます。
現在行が空の場合は、予約済みスペースを次に置き換えx
(パターンスペースが空なので予約済みスペースを消去する効果もあります)、すべての改行を空白に置き換えて最初の文字を削除します(追加文字になります)。空白文字)。
答え2
awk
短絡モードで:
awk -v RS= -v FS='\n' -v OFS=' ' '{
for (i=1;i<=NF;i++) {
printf "%s%s", $i, (i<NF ? OFS : ORS)
}
}' file
HEAD1 IF FI GH
HEAD2 PU GT
HEAD3 FG DF YT GU
RS=
この設定の後RS
、入力レコードは空白行で区切られます。FS='\n'
これにより、各段落の各行をレコードフィールドとして扱うことができます。for
すべてのフィールドを繰り返し、printf
条件式で印刷しますternary expression
。 exp1 がi<NF
true を返す場合はOFS
実行し、そうでない場合はORS
実行します。