2016-10-06 2 views
0

私はタブで区切られた> 10,000行の行と、行ごとに可変の数の列(33-35)を持っています。 34列と行のためにAWK if節でフィールドを結合する

、私は1つに、列3-4を崩壊したいと思います:

col1 col2 col3 col4 ... col34 
index1 tool  kit math   new 

へ - >

同様に
col1 col2 col3 ... col33 
index1 tool kit;math  new 

、35列のために、私はしたいと思います列3-5を1つに折り畳む。 AWKとNFを利用してこれを達成する方法があるかもしれないということがわかります。任意のヒントやヘルプ?

+0

今のところ約35列を忘れて、入力と希望する出力がどのように表示されるかを正確に示すより少ない列で簡単な例を作ってみましょう。 –

答えて

0

のawkでは:

NF>5 {           # if more than 5 (33) fields 
    for(i=(NF-5)-1; i>=0; i--)     # execute next for once or twice 
     for(j=3+i; j<=NF; j++)     
      $j=(j<4+i ? $j ";" : "") $(j+1) # catenate once or twice on i 
    NF=5 
} $1=$1          # is this a problem? 

を実行して:いくつか270 lines of TXR Lispawk paradigm

$ awk -v OFS='\t' -f program.awk karakfa\'s.txt 
col1 col2 col3 col4 col5 
1  2  3;4  5  6 
1  2  3  4  5 
1  2  3;4;5 6  7 
0

はあなたの二、三の条件指定されたフィールドをループにforループを使用して、この短くすることができますが、長い手(とawkの初心者のためのより理解しやすい)は、次のとおりです。

awk 'NF==35{print $1,$2,$3$4$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35} NF==34{print $1,$2,$3$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34} NF==33{$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33}' yourfile.txt 

だことレコードにあるフィールドの数に基づいてフィールドの異なる組み合わせを印刷しているだけです。

+0

ありがとう!これは非常に有用であり、理にかなっています。このフォーマットでは、すべての可能性をあらかじめ指定しなければなりませんか?たとえば、NF <33の行を除外しますか?私はNF == 34とNF == 35で行を具体的に変更し、それ以外はそのままにしておきたいと思います。 – AMS

+0

これは、33,34、または35フィールドではないレコードを除外します。その最後の条件を 'NF <= 33'または' NF!= 34 && NF!= 35'または 'NF <34 || NF> 35 'に変更することができます。 – JNevill

0

awkはこちらです。代わりに5〜7列を使用しました。

$ cat file 
col1 col2 col3 col4 col5 
1  2  3  4  5  6 
1  2  3  4  5 
1  2  3  4  5  6  7 

$ awk -v OFS='\t' 'NR==1{print; next} 
        NF>5{$3=$3 $4; t=1} 
        NF>6{$3=$3 $5; t=2} 
         t{for(i=4;i<=NF;i++) $i=$(i+t); 
         NF=NF-t; t=0}1' file 

col1 col2 col3 col4 col5 
1  2  34  5  6 
1  2  3  4  5 
1  2  345  6  7 
0

TXR実装:

ウォームアップ:すべてのファイル間で合体基本的なコラム:

$ txr -e '(awk ((>= nf 4) (set [f 2..4] (list `@[f 2];@[f 3]`))) 
       (t))' 
1 
1 
1 2 
1 2 
1 2 3 
1 2 3 
1 2 3 4 
1 2 3;4 
1 2 3 4 5 
1 2 3;4 5 

フィールドがリストfはなく、ドル記号を含む特殊な構文上のガジェットなので、スライスの割り当てを受けやすい:(set [target-sequence n..m] source-sequence)は(mの排他的、nからmに)n..mスライスを置き換えtarget-sequencesource-sequenceで。インデックスはそう第三及び第四のフィールドを置き換えるために、我々はスライス2..4を表し、ゼロからである:4

(t)を含まない、すなわち、インデックス2と3は、Awkのの1に類似した条件のない条件とアクションの句であり、 :rec$0に相当)を出力する暗黙的な(prn)フォームをトリガします。 tは、nil以外の値はすべてtrueですが、論理的にブールtrueを表す自己評価シンボルです。上記のスライスの割り当てなどによって、fが特定の方法で操作された場合、recは、をその間に挿入することによって、フィールドから自動的に再構成されます.Awk Classicのフィールドツイディリングは$0を再構成します。

次に、どのように見出しを印刷した後、無視されるように、第1行の取り扱いについて:

$ txr -e '(awk ((= nr 1) (prn) (next)) 
       ((>= nf 4) (set [f 2..4] (list `@[f 2];@[f 3]`))) 
       (t))' 
1 2 3 4 5 
1 2 3 4 5 
1 2 3 4 5 
1 3 3;4 5 

次に、我々は、35対34のための変更範囲に関する要件を有します。どのように私たちは "34列以上"の条件を使用しますか?

[f 2..4] 

[f (if (> nf 34) 2..5 2..4))] 

しかし、我々は変数に条件付きの範囲をバインドする場合は統一された方法でそれを行うと、その後、いくつかの中でそれを使用することができます

へ:移動範囲は、表現を変えることによって処理することができます場所。私たちは条件を一度テストするだけです。結果は:バッククォート区切り準文字列リテラルの内部

$ txr -e '(awk ((= nr 1) (prn) (next)) 
       ((>= nf 4) (let ((r (if (> nf 34) 2..5 2..4))) 
          (set [f r] (list `@{[f r] ";"}`)))) 
       (t))' 
col1 col2 ... 
col1 col2 ... 
1 2 3 4 5 6 7 8 9 0 A B C D E F G H I J K L M N O P Q R S T U V W X Y 
1 2 3;4;5 6 7 8 9 0 A B C D E F G H I J K L M N O P Q R S T U V W X Y 
1 2 3 4 5 6 7 8 9 0 A B C D E F G H I J K L M N O P Q R S T U V W X 
1 2 3;4 5 6 7 8 9 0 A B C D E F G H I J K L M N O P Q R S T U V W X 

、構文@{[seq range] string}セパレータとして文字列を使用して、配列のスライスを補間します。範囲rを単純に内挿します。これは、削除して結果の文字列に置き換える範囲と同じです。私たちは34列以上あるかどうかについて条件付きでrを切り替えるので、テストはちょうど1回だけで、は2か所で使用されます。

+0

本当にありがとうございました! – AMS