如何使用 BASH 将 .txt 文件数据存储在 CSV 文件的不同列中?

How to store .txt file data in different columns of a CSV file using BASH?

我有一个具有以下数据结构的 .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

这是执行此操作的 awk 脚本:

#!/usr/bin/awk -f

BEGIN {
    OFS=","
    colnum=0
}

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

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

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

如果 ed 在 unix/linux 实用程序的帮助下 available/acceptable。

只有一个文件。

脚本my_script

#!/bin/sh

ed -s "" <<-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 "" <<-EOF
 g/.\{1,\}/s/^ //\
 s/ seconds//
 w tmpa.$$
 %d
 r !pr -t4 -s, tmpa.$$
 d
 w tmpa.$$
 E 
 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.$$ 但它是 removed/deleted 在 !rm tmpa ... 所在的行在.

  • 输出写入文件result.csv

  • Ed 是一个文件编辑器,不是像 awkbash 这样的 scripting/programming 语言,并不是每个人都喜欢 ed,但它仍然是 option/solution.

这可能适合您(GNU sed、csplit 和粘贴):

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

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

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

使用逗号作为字段分隔符,使用粘贴将分隔的部分组合回一个部分。

清理遗留文件。

在每个 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