【问题标题】:How to store .txt file data in different columns of a CSV file using BASH?如何使用 BASH 将 .txt 文件数据存储在 CSV 文件的不同列中?
【发布时间】:2021-09-25 14:05:10
【问题描述】:

我有一个具有以下数据结构的 .txt 文件:

Scan Times:
 33.3 seconds
 77.4 seconds
 33.3 seconds
 77.4 seconds

Check Times:
 110.30 seconds
 72.99 seconds
 72.16 seconds
 110.30 seconds

Move Times:
 73.66 seconds
 90.77 seconds
 72.87 seconds
 71.75 seconds
 
Switch Times:
 92.0 seconds
 78.6 seconds
 77.8 seconds
 84.9 seconds

我现在想要获取该 .txt 文件并创建一个具有以下格式的 CSV 文件。

到目前为止,我的 bash 脚本有一个非常基本的布局,但我不确定如何继续:

inputFiles=("./Successes/SuccessSummary.txt" "./Failures/FailSummary.txt")
touch results.csv

for file in "${inputFiles[@]}"
do 
    while IFS= read -r line
    do
        #echo $line
        if [ "$line" = "Scan Times:" ]
        then 
        fi

        if [ "$line" = "Check Times:" ]
        then 
        fi

        if [ "$line" = "Move Times:" ]
        then 
        fi
        
        if [ "$line" = "Switch Distances:" ]
        then 
        fi
    done < "$file"
done

【问题讨论】:

  • 你试过谷歌搜索`bash pivot csv吗?另外,您是否尝试将两个输入文件写入同一个/单个输出文件,如果是,请提供两个输入文件的示例内容和所需的输出(匹配输入文件中的示例数据)
  • 我还没有,我将研究 bash pivot。这两个文件的格式完全相同,所以我的最终 CSV 应该有 8 列数据。我正计划使用计数器来增加我的数据打印到的列。 @markp-fuso

标签: bash csv file sed txt


【解决方案1】:

这是一个 awk 脚本:

#!/usr/bin/awk -f

BEGIN {
    OFS=","
    colnum=0
}

/:$/ {
    data[++colnum,1]=$0
    rownum=1
}

/seconds$/ {
    data[colnum,++rownum]=$1
}

END {
    for (r = 1; r <= rownum; r++) {
        for (c = 1; c <= colnum; c++) {
            printf "%s%s", data[c,r], (c == colnum ? RS : OFS)
        }
    }
}

例子:

$ ./pivot input.txt
Scan Times:,Check Times:,Move Times:,Switch Times:
33.3,110.30,73.66,92.0
77.4,72.99,90.77,78.6
33.3,72.16,72.87,77.8
77.4,110.30,71.75,84.9

【讨论】:

    【解决方案2】:

    如果 ed 在 unix/linux 实用程序的帮助下可用/可接受。

    一个文件。

    脚本my_script

    #!/bin/sh
    
    ed -s "$1" <<-EOF
     g/.\\{1,\\}/s/^ //\\
     s/ seconds//
     w tmpa.$$
     %d
     r !pr -t4 -s, tmpa.$$
     d
     !rm tmpa.$$
     w result.csv
     %p
     Q
    EOF
    

    然后

    ./myscript ./Successes/SuccessSummary.txt
    

    result.csv的输出和内容

    Scan Times:,Check Times:,Move Times:,Switch Times:
    33.3,110.30,73.66,92.0
    77.4,72.99,90.77,78.6
    33.3,72.16,72.87,77.8
    77.4,110.30,71.75,84.9
    

    有两个文件。 (只是将第一个文件的内容与第二个文件一起使用。)

    #!/bin/sh
    
    ed -s "$1" <<-EOF
     g/.\\{1,\\}/s/^ //\\
     s/ seconds//
     w tmpa.$$
     %d
     r !pr -t4 -s, tmpa.$$
     d
     w tmpa.$$
     E $2
     g/.\\{1,\\}/s/^ //\\
     s/ seconds//
     w tmpb.$$
     %d
     r !pr -t4 -s, tmpb.$$
     d
     w tmpb.$$
     %d
     r !pr -mts, tmpa.$$ tmpb.$$
     %p
     w result.csv
     !rm tmp[ab].$$
     Q
    EOF
    

    然后

    ./myscript ./Successes/SuccessSummary.txt ./Failures/FailSummary.txt
    

    result.csv 的输出和内容

    Scan Times:,Check Times:,Move Times:,Switch Times:,Scan Times:,Check Times:,Move Times:,Switch Times:
    33.3,110.30,73.66,92.0,33.3,110.30,73.66,92.0
    77.4,72.99,90.77,78.6,77.4,72.99,90.77,78.6
    33.3,72.16,72.87,77.8,33.3,72.16,72.87,77.8
    77.4,110.30,71.75,84.9,77.4,110.30,71.75,84.9
    

    • ed 脚本有两个临时文件 tmpa.$$tmpb.$$,但它在 !rm tmpa ... 所在的行被删除/删除。

    • 输出写入文件result.csv

    • Ed 是文件编辑器,而不是像 awkbash 这样的脚本/编程语言,也不是每个人都喜欢 ed,但它仍然是一个选项/解决方案。

    【讨论】:

      【解决方案3】:

      这可能对您有用(GNU sed、csplit 和粘贴):

      sed '/\S/!d;s/^ \| seconds//g' file |
      csplit -zs - '/:/' '{*}' && paste -d, xx* && rm xx*
      

      使用 sed 删除空行和不需要的空格和文字。

      使用 csplit 将文件拆分为单独的部分,即 xx00 ...

      使用 paste 将分开的部分组合成一个,使用逗号作为字段分隔符。

      清理遗留文件。

      【讨论】:

        【解决方案4】:

        在每个 Unix 机器上的任何 shell 中使用任何 awk:

        $ cat tst.awk
        BEGIN { RS=""; FS="\n"; OFS="," }
        {
            for (i=1; i<=NF; i++) {
                if (i > 1) {
                    gsub(/[^0-9.]/,"",$i)
                }
                vals[i,NR] = $i
            }
        }
        END {
            for (i=1; i<=NF; i++) {
                for (j=1; j<=NR; j++) {
                    printf "%s%s", vals[i,j], (j<NR ? OFS : ORS)
                }
            }
        }
        

        $ awk -f tst.awk file
        Scan Times:,Check Times:,Move Times:,Switch Times:
        33.3,110.30,73.66,92.0
        77.4,72.99,90.77,78.6
        33.3,72.16,72.87,77.8
        77.4,110.30,71.75,84.9
        

        【讨论】:

          猜你喜欢
          • 2017-11-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-19
          • 2015-10-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多