2012-02-01 55 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 
相关问题