代码之家  ›  专栏  ›  技术社区  ›  Parker Clark

通过Bash操作csv中的特定列?

  •  0
  • Parker Clark  · 技术社区  · 1 年前

    我正在写一个脚本来设置一个csv文件,其中包含从另一个.txt文件解析的数据。我有几个特定的列,以及这个程序的流程,我使用这些列从.txt中获取数据。我只是不确定如何继续,因为我希望下一个专栏与我正在查看的内容的当前迭代相关联。

    我的通用代码是这样的:

    #!/bin/bash 
    COLUMNS=(1 2 3) 
    
    for column in "${COLUMNS[@]}"; do
       echo "${COLUMNS[@]}" > someCSVFile.csv
       parsedText=$(sed -n '/'$column-'/,/^${/^$/d; p}' someTextFile.txt)
       for line in "${parsedText[@]}"; do
          echo "${line}" >> someCSVFile.csv
       done
    done 
    

    当我解析代码时,文本以如下格式返回:

    a
    b
    c
    

    例如,假设COLUMN1返回“abc”(采用上述格式),COLUMN2返回“def”,依此类推。理想情况下,我应该在第二个For循环中传递给CSV,如下所示:

    1,2,3
    a,d,g
    b,e,h
    c,f,i
    

    但相反,输出将是:

    1
    a
    b
    c
    2
    d
    e
    f
    3
    g
    h
    i
    

    有没有一种方法,基于循环的迭代,我可以移动到csv的下一列?

    1 回复  |  直到 1 年前
        1
  •  0
  •   David C. Rankin    1 年前

    您可以在bash中做您想做的事情,但它有些不灵活。逻辑有点紧张,因为输出是 以线条为导向 ,但你的逻辑是 以列为导向 。不过,bash还是很有能力的,可以把圆钉子插在方洞里。

    基本上,你想循环1-3,然后索引字母0、2、5(例如。 "a,d,g" )对于第一行,然后为第二行索引字母1、3、6,依此类推。

    您可以使用简单的大括号展开创建字母数组,例如。 letters=( {a..z} ) ,然后在原始数组上循环 1,2,3 。总而言之,你可以做到:

    #!/bin/bash
    
    cols=(1 2 3)          # your example
    letters=( {a..z} )    # fill array with a-z using brace expansion
    
    str="${cols[*]}"      # convert array to string of space separated values
    echo "${str// /,}"    # echo to stdout with commas
    
    ## loop 1-3 and output corresponding letter desired using indexes
    for c in "${cols[@]}"; do
      echo "${letters[c-1]},${letters[c+2]},${letters[c+5]}"
    done
    

    ( 笔记 不要使用大写的变量名,这些名称通常是为bash系统变量和环境保留的)

    使用/输出示例

    脚本在 cols.sh 你会得到:

    $ bash cols.sh
    1,2,3
    a,d,g
    b,e,h
    c,f,i
    

    您可以使用将其全部重定向到一个文件 bash cols.sh > somefile .

    如果您还有其他问题,请告诉我。

    (编辑后添加逗号)

    (第二次编辑以消除对的调用 sed ,而是使用带子字符串替换的内置参数扩展)

    推荐文章