行を列に変換

行を列に変換

行ブロックが空の行に分割され、行を列に変換する必要があるこのような入力があります。

入力する

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 }; 11


代わりに使用してください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<NFtrue を返す場合はOFS実行し、そうでない場合はORS実行します。

関連情報