2012-02-01 50 views
1

我有2個的CSV文件:a.txt中包含數據和a_props.txt描述列的類型,例如:bash:如何從變量行長度的CSV文件中獲取一列?

A.TXT:

john,smith,[email protected],30, 
peter,jones,27 

a_props.txt:

name,surname,email,age 
name,surname,age 

如何根據從a_props.txt獲取的索引從a.txt獲取一種類型的數據?

如:年齡

30,27 

30 
27 
+0

這是比較正常的,以不同的文件格式分割成單獨的文件,所以你需要一個A.TXT和b.txt對應a_props.txt和b_props。 txt(假設你正在處理2行以上的數據)。你可以重構這些數據文件的創建,還是一個嚴格的約束?您也可以構建過濾器來獲取一個文件,並根據需要將它們變成b,c,....取決於您擁有多少個佈局。祝你好運。 – shellter 2012-02-01 18:33:26

回答

3

您可以使用paste合併由線和awk兩個文件行來檢查是否有任何你正在尋找匹配的屬性名稱:

paste -d, a_props.txt a.txt | awk -v PROP='age' -v FS=',' '{for (i=1; i<=NF/2; i++) if ($i == PROP) print $(NF/2+i)}' 

在這個例子中,輸出將是:

30 
27 

請注意,您只需更改PROP=<property>即可獲取其他某列的值。

編輯:修正了PROP不是記錄的最後一個字段的情況。

+0

只有屬性文件與數據字段具有相同的行數時,它才起作用。 – 2012-02-01 20:51:09

+0

@ZsoltBotykai這是正確的,這是我根據OP給出的例子所做的假設。 – jcollado 2012-02-01 21:09:25

+0

很好的解決方案,謝謝。打印$(i * 2) - >打印$(NF/2 + i) – 2012-02-01 22:41:40

1

使用過程中替換和額外的文件描述符,以獲得額外的流讀取,並宣讀了道具和數據文件並行:

key=age 

exec 9< <(tr , " " < a_props.txt) 10< <(tr , " " < a.txt) 

while read -u 9 -a props ; do 
    read -u 10 -a data 
    for ((ix=0 ; $ix < ${#props[*]} ; ix++)); do 
     if [ "${props[$ix]}" == $key ]; then 
      echo ${data[$ix]} 
     fi 
done 
done 

進程替換是bash的特定,且不會在香草SH工作。

此外,要非常小心「csv」文件是什麼。一旦你添加引用的字段等,他們變得更難以解析。在這一點上我會在其他一些語言(例如,Text::CSV在Perl或csv包tcllib)

0
awk -F "," '{ a=1 
       while ((getline p < ARGV[2]) > 0) { 
        props[a]= 
        a++ 
       } 
       close(ARGV[2]) 
      } 
      ARGIND > 1 { exit } 
      { for (elem in props) { 
        if (length(props[elem]) = NF) { 
         split(props[elem],header,",") 
         for (item in header) { 
          data[header[item]+=$i "," 
         } 
        } 
      } 
      END { 
        for (elem in data) { 
         split(gensub(",$","","g",data[elem]),d,",") 
         print elem ":" 
         for (e in d) { 
          print d[e] 
         } 
        } 
       }' a.txt a.props.txt 

這可能會實現使用現有的CSV包,但我沒有測試它。我不會推薦它與真正的大文件,因爲腳本唾手可得的內存。而會發生什麼,如果a_props.txt包含兩個或多個行具有相同字段長度例如爲:

name,age 
name,email 

這種情況是不以上腳本處理!並且該腳本的參數順序是重要的

1

這可能會爲你工作:

paste a_props.txt a.txt | 
awk '{split($1,a,",");split($2,b,",");for(x in a){if(a[x]==v)print b[x]}}' v=age 
相關問題