sed を使用したテーブルの行の結合

sed を使用したテーブルの行の結合

クエリには次の表がありますが、+区切り文字は、次の例に示すように、「説明」の下に新しい行を作成することです。


TYPE+DESCRIPTION+PRIORITY+DATE
1+text1+HIGH+Aug 15
+text2  
2+text+LOW+Aug 11
3+text+LOW+Aug 11
4+text1+HIGH+Aug 15
+text2  
+text3

sedを使用して次のように見えるようにするにはどうすればよいですか?

TYPE    DESCRIPTION      PRIORITY DATE
1       text1 text2      HIGH     Aug 15
2       text             LOW      Aug 11
3       text             LOW      Aug 11
4       text text2 text3 HIGH     Aug 15

私は試した:

sed -n '1{h;n};/^ *+ */{s// /;H;n};{x;s/\n//g;p};${x;p}' 

しかし、エラーが発生しました(sed:コマンドが壊れています)。ありがとうございます。

答え1

awk '
    BEGIN{OFS=FS="+"}
    {sub(/[[:blank:]]+$/,"")}  #Removes trailing blanks
    NF==4{print line;line=$0}
    NF==2{x=$2;$0=line;$2=$2" "x;line=$0}
    END{print line}
' file | column -ts "+"

その背後にある主なアイデアは、ifが前の行のNF==22番目のフィールド$2に2番目のフィールドを置くことです。それで何が起こりますか?

1+text1+HIGH+Aug 15 #Puts this in "line" variable
+text2              #Transfer 2nd field to "line" second field
# Resulting in...
1+text1 text2+High+Aug 15

column+この微細な最終出力を生成するために出力から削除されました。

TYPE  DESCRIPTION        PRIORITY  DATE
1     text1 text2        HIGH      Aug 15
2     text               LOW       Aug 11
3     text               LOW       Aug 11
4     text1 text2 text3  HIGH      Aug 15

答え2

「ドメイン不可知論」を作るawk

tac file | awk 'BEGIN{FS="+"}
    {flds=(NF>flds)?NF:flds;for (i=1; i<=NF; i++) {f=(length($i)>0)?gensub(/ +$/,"","g",$i)" ":"";fld[i]=f fld[i]}}
    $1>0{for (i=1; i<=flds; i++) printf fld[i]"+"; printf "\n"; delete fld}' | 
    tac | column -ts "+"

TYPE   DESCRIPTION         PRIORITY   DATE     
1      text1 text2         HIGH       Aug 15   
2      text                LOW        Aug 11   
3      text                LOW        Aug 11   
4      text1 text2 text3   HIGH       Aug 15  

$ 1が空でなく設定されているときに印刷する時間であることがわかるように、ファイルを反転します。FS

tac file | awk 'BEGIN{FS="+"}

最大数を計算しflds、フィールドを繰り返し、切り取り、空白を確認し、フィールドごとに配列にロードして集計します。

    {flds=(NF>flds)?NF:flds;for (i=1; i<=NF; i++) {f=(length($i)>0)?gensub(/ +$/,"","g",$i)" ":"";fld[i]=f fld[i]}}

空でない場合は$1ラインを出力し、配列をリセットします。

    $1>0{for (i=1; i<=flds; i++) printf fld[i]"+"; printf "\n"; delete fld}' | 

パイプを通してtac裏返してcolumn美しくするために使用してください。

    tac | column -ts "+"

編集する

2番目のループは本当に気に入らず、パイプのハンマーで打つことがgensubできるときに各フィールドで停止してテストを簡素化します。sed優雅な感じではありませんね。

だからここにゴルフをするバージョンはただ感じる私にとってより良い:

tac file | awk 'BEGIN{FS="+"}
    {flds=(NF>flds)?NF:flds;
        for (i=1; i<=NF; i++) {fld[i]=$i" "fld[i];
        if ($1) printf fld[i]"+"}}
    $1{ printf "\n"; delete fld}' |
    sed -E "s/  +/ /g" | tac | column -ts "+" 

答え3

戻って、sedバージョン間の考えられる違いを読んで最初から書き直してください。これがうまくいくことを願っています:

:r
    $!N
    y:+:,:
    /\n,/{
        s:^\([^,]\{1,\},[^,]\{1,\}\)\([^\n]\{1,\}\)\n,\([^ \n]\{1,\}\).*$:\1 \3\2:
        br
    }
    $!P
    $!D

出力:

TYPE,DESCRIPTION,PRIORITY,DATE
1,text1 text2,HIGH,Aug 15
2,text,LOW,Aug 11
3,text,LOW,Aug 11
4,text1 text2 text3,HIGH,Aug 15

答え4

perl -0pe 'while(s/(.*?)\+(.*?)\+(.*)\n\+(.*)/$1+$2 $4+$3/g){}' file
  • perl -0 - すべての入力を飲み込む
  • s/(.*?)\+(.*?)\+(.*)\n\+(.*)/$1+$2 $4+$3/gA+B+...C\n+D可能であれば切り替えてくださいA+B D+...C

関連情報