次の行のセルが空の場合に列の値を繰り返す方法

次の行のセルが空の場合に列の値を繰り返す方法

入力ファイル

CARD   SG   CLASS   ATT  
11      0   DAS     YES 
CARD   SG   CLASS   ATT
12      0   ECT     YES
CARD   SG   CLASS   ATT
13      0   VAS     YES
        1   DAS     NO
CARD   SG   CLASS   ATT
14      0   SAT     YES
CARD   SG   CLASS   ATT
15      0   CDT     YES
        1   VEG     YES
        2   GAT     NO

予想される出力:

 CARD   SG   CLASS   ATT
 11     0   DAS      YES    
 12     0   ECT      YES
 13     0   VAS      YES
 13     1   DAS      NO
 14     0   SAT      YES
 15     0   CDT      YES
 15     1   VEG      YES
 15     2   GAT      NO

私がしたこと:

awk ' /YES|NO/{VAL=$1};/ATT/{Print "CARD" "SG" "CLASS" "ATT" };/YES|NO/{ print VAL, $2, $3, $4} ' SCGR.txt  | column -t   

11  0    DAS  YES
12  0    ECT  YES
13  0    VAS  YES
1   DAS  NO
14  0    SAT  YES
15  0    CDT  YES
1   VEG  YES
2   GAT  NO

助けてください

答え1

これを試してください(すべてのヘッダー行が正確に等しいと仮定します)。

awk '  NR==1{header=$0; count=NF; print; next}
       ($0~header) {next}
       (NF==count) {col1=$1}
       (NF<count)  {printf("%s",col1)}
       1 ' infile | column -t

答え2

1 つのライナーのデバッグ - いくつかの小さな問題:

  • Print--print
  • /ATT/{Print "CARD" "SG" "CLASS" "ATT" }-/ATT/{print}または/ATT/;
  • /YES|NO/{VAL=$1}3つのフィールドレコードでもトリガーされ、以前に保存された値が消去されます。(順序を変更するか、$4 ~ /YES|NO/)

バリエーション:

awk 'NF==4{v=$1;print} NF==3{print v,$0}' 

余分なヘッダーとインデントを削除します。

awk '/^CARD/ && NR>1 { next } 
     NF==4           { v=$1;print } 
     NF==3           { print v,$0 }'

答え3

列の配置を気にせず、空白で区切られた正規化されたデータだけが必要な場合、基本的なパターンは次のようになります。

awk -F' +' '{ $1 = ($1 ~ /^$/ ? prev : $1); prev = $1; print }'

デフォルトのスペースと等しくないカスタム フィールド セパレーターを設定すると、フィールドの真の分離が実現されます。レコードがセパレーターに一致する文字で始まる場合、空のフィールドが区切られます。

デフォルトでは、Awk は分離せず、トークン化します。つまり、各レコードから 1 つ以上の非空白/非改行文字のシーケンスであるトークンを抽出します。つまり、先頭と末尾の空白/改行は無視されます。したがって、列 1 が欠落している場合は、列 2 の値が列 1 になります。

セパレータ正規表現を使用すると/ +/、真の分離動作が得られます。 のような先頭と末尾のスペースを含むレコードは1 2 3 4として扱われます<SEP>1<SEP>2<SEP>3<SEP>4<SEP>。したがって、、、...、、の 6 つのフィールドがあります。""最初"1""4"フィールドの前と最後のフィールドの後に""フィールドがあります。<SEP>

ところで、最初のレコードにフィールドが欠落している可能性がある場合は、 のデフォルトが必要であることは明らかですprev。また、見出しにロジックを適用したくありません。また、三項演算子を : に置き換えてみましょうif。つまり、次のようになります。

awk 'BEGIN { FS = " +"; prev = 0 }
     NR == 1
     NR > 1 { if ($1 == "") $1 = prev
              print
              prev = $1 }'
FOO BAR BAZ
FOO BAR BAZ
  2 3 4
0 2 3 4
1 2 3 4
1 2 3 4
  2 3 4
1 2 3 4

答え4

教育のためだけにsedの決定

sed '
    1b                             #output 1st line (header)
    $!N                            #add next line to operate 2 lines altogether
    s/\(.*\)\n\(CARD.*\)/\2\n\1/   #move line with CARD to first place 
    /^CARD/D                       #delete line with CARD and go to start
    s/^\(\([0-9]*\s*\).*\n\)\s\s*/\1\2/ 
                                   #repeat 1st field of 1st line if empty in 2nd
    /\n/{P;D}                      #print&remove 1st line, go to start 
    '

関連情報