2017-01-11 8 views
1

私は例えば,:構造体/トークンに空白と空白を含むテーブルを解析するには?

$cat t.txt 

ID Name   Callin Link Auth CCOS Msg Channel Priv Limit 
1     false false  true  USER 
2 Administrator false false  true  ADMINISTRATOR 

「USER」を配列またはトークン化にテーブルを解析するが、位置を保持しなければならないが、代わりに6のフィールド値を持つ必要があり、コードのほとんどは、偶数フィールドの区切り文字と5として私を与えますタブとして

空白のフィールドに問題があります。理想的には、私はフィールドを印刷したい

while read col1 col2 col3 col4 col5 col6 
do 
    echo "Col1 : $col1" 
    echo "Col2 : $col2" 
    echo "Col3 : $col3" 
    echo "Col4 : $col4" 
    echo "Col5 : $col5" 
    echo "Col6 : $col6" 
done < t.txt 

cat t.txt | awk 'BEGIN { FS = "[ \t]+" } ; { print $1 "\t" $6}' 

:どのように私は効果的に私が試した配列

コード、それらのすべてが空白値をスキップして、それをキャプチャdoesntのにそれを追加します

echo field[0], field[6] # 1 , USER and 2, ADMINISTRATOR 

答えて

2
$ sed -e 's/^\([0-9]*\)\s.*\s\([^ ]*\)$/\1,\2/g' < t.txt 
ID Name   Callin Link Auth CCOS Msg Channel Priv Limit 
1,USER 
2,ADMINISTRATOR 
+0

とにかくヘッダーをスキップするには? – Victor

+1

'sed -e '1 {h; d}' -e ...' –

+0

h; dはどういう意味ですか? – Victor

3

のようなあなたのファイルは本当にトンを持っている場合ab区切り文字を使用すると、awkはそれを正しく解析します。空白だけがある場合、GNU awkは固定幅の境界で解析できます。そうでなければ、何とか前処理しなければならないでしょう。そこにないものを解析することはできません。

データを取って、タブ区切り文字を追加しました。私は非空白が続く任意の二つの空間の文字列を探し、そして特別に第1データ線取り扱わ:

$ sed -E 's/ ([^ ])/\t\1/g; s/^1/1\t/;' fixed.dat | cat -vt 
ID^IName  ^ICallin^ILink Auth^ICCOS Msg ^IChannel Priv Limit 
1^I     ^Ifalse ^Ifalse ^Itrue  ^IUSER 
2 ^IAdministrator ^Ifalse ^Ifalse ^Itrue  ^IADMINISTRATOR 

だけのawkを見つけるに解析することができます。

$ sed -E 's/ ([^ ])/\t\1/g; s/^1/1\t/;' fixed.dat | awk -F\\t '{print $6}' 
Channel Priv Limit 
USER 
ADMINISTRATOR 

は、固定使用するにはwidthカラムをGNU awkに追加し、FIELDWIDTHS文字列を設定します。ここでは、プログラムで行うの:

BEGIN { 
    titles = "ID Name   Callin Link Auth CCOS-Msg Channel-Priv-Limit" 

    pos = 1 
    sep = "" 
    while(match(substr(titles, pos),/+/) > 0) { 
    pos += RSTART + RLENGTH - 1 
    FIELDWIDTHS = FIELDWIDTHS sep RSTART + RLENGTH - 1 
    sep = " " 
    } 
    FIELDWIDTHS = FIELDWIDTHS sep length(titles) - pos 

    print "FIELDWIDTHS:", FIELDWIDTHS 
} 

{ 
    OFS = "|" 

    print $1, $2, $3, $4, $5, $6, $7, $8, $9 
} 

結果:

$ awk -f fixed.awk fixed.dat 
FIELDWIDTHS: 4 13 8 5 6 11 17 
ID |Name   |Callin |Link |Auth |CCOS Msg |Channel Priv Limi|| 
1 |    | fals|e f|alse | true | USER|| 
2 |Administrator| fals|e f|alse | true | ADMINISTRATOR|| 

それが列オフセットを計算するためにタイトル行を使用し、あなたのタイトルはあなたのデータの上にラインアップしていないので、少し間違っているのです。しかし、これがあなたの状況であれば、列を解析するためにFIELDWIDTHS文字列を修正する方法を見ることができます。

あなたが与えられたラインと間違って何かわからない場合は、ラインを検討する私のお気に入りの方法は少し複雑ですが、非常に高速かつ不滅:

$ sed -E 's/ ([^ ])/\t\1/g; s/^1/1\t/;' fixed.dat | 
    sed -ne '2 {p;q;}' | tr \\t \\n | nl -ba 
1 1 
2      
3 false 
4 false  
5 true  
6 USER 

(1)chosesがセッド行を印刷する(そして終了する、ファイルが大きい場合はずっと速くする)。 tr(1)は区切り文字を改行に変換し、nl(1)はその行番号を付けます。行にタブがない場合は、すぐに表示されます。

$ sed -E 's/ ([^ ])/\t\1/g' fixed.dat | sed -ne '2 {p;q;}' | tr \\t \\n | nl -ba 
1 1     
2 false 
3 false  
4 true  
5 USER 

最後に、シェルを使用してファイルを解析しないでください。特に構文解析用に設計されているだけでなく、awkは、1)ループが解釈されず、2)スクリプトが1つのプロセスとして実行されるため、はるかに高速です。あなたがファイル名のリストではないものの上でシェルをループしているなら、あなたはあまりにも頑張っています。

関連する問題