Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 使用AWK将文件名打印为CSV_Bash_Csv_Awk_Sed_Cat - Fatal编程技术网

Bash 使用AWK将文件名打印为CSV

Bash 使用AWK将文件名打印为CSV,bash,csv,awk,sed,cat,Bash,Csv,Awk,Sed,Cat,我有一个小脚本来比较一堆CSV文件中的一些列。 它工作得很好,但有些事情让我感到不安 代码如下: FILES=./* for f in $FILES do cat -v $f | sed "s/\^A/,/g" > op_tmp.csv awk -F, -vOFS=, 'NR == 1{next} $9=="T"{t[$8]+=$7;n[$8]} $9=="A"{a[$8]+=$7;n[$8]} $9=="C"{c[$8]+=$7;n[$8]} $9=="R"{r[$8]

我有一个小脚本来比较一堆CSV文件中的一些列。 它工作得很好,但有些事情让我感到不安

代码如下:

FILES=./*
for f in $FILES

do
    cat -v $f | sed "s/\^A/,/g" > op_tmp.csv
    awk -F, -vOFS=, 'NR == 1{next} $9=="T"{t[$8]+=$7;n[$8]} $9=="A"{a[$8]+=$7;n[$8]} $9=="C"{c[$8]+=$7;n[$8]} $9=="R"{r[$8]+=$7;n[$8]} $9=="P"{p[$8]+=$7;n[$8]} END{ for (i in n){print i "|" "A" "|" a[i]; print i "|" "C" "|" c[i]; print i "|" "R" "|" r[i]; print i "|" "P" "|" p[i]; print i "|" "T" "|" t[i] "|" (t[i]==a[i]+c[i]+r[i]+p[i] ? "ERROR" : "MATCHED")} }' op_tmp.csv >> output.csv
    rm op_tmp.csv
done
我只是想解释一下: 我获取目录中的所有文件,然后使用CAT替换管道|的除数^A。 然后,我使用awk联机器比较我需要的列,并将结果打印到output.csv

但是现在我想在每次循环之前打印文件名。 我尝试在同一行中使用cat sed和awk并打印$FILENAME,但它不起作用:

cat -v $f | sed "s/\^A/,/g" | awk -F, -vOFS=, 'NR == 1{next} $9=="T"{t[$8]+=$7;n[$8]} $9=="A"{a[$8]+=$7;n[$8]} $9=="C"{c[$8]+=$7;n[$8]} $9=="R"{r[$8]+=$7;n[$8]} $9=="P"{p[$8]+=$7;n[$8]} END{ for (i in n){print i "|" "A" "|" a[i]; print i "|" "C" "|" c[i]; print i "|" "R" "|" r[i]; print i "|" "P" "|" p[i]; print i "|" "T" "|" t[i] "|" (t[i]==a[i]+c[i]+r[i]+p[i] ? "ERROR" : "MATCHED")} }' > output.csv

有人能帮忙吗?

您可以更好地重写整个脚本,但假设它能满足您现在的需要,只需添加

echo$f>>output.csv

在awk电话之前

如果要在每个awk输出行中添加文件名,必须将其作为参数传递,即

 awk ... -v fname="$f" '{...; print fname... etc
重写:

for f in ./*; do
    awk -F '\x01' -v OFS="|" '
        BEGIN { 
            letter[1]="A"; letter[2]="C"; letter[3]="R"; letter[4]="P"; letter[5]="T" 
            letters["A"] = letters["C"] = letters["R"] = letters["P"] = letters["T"] = 1
        }
        NR == 1 {next} 
        $9 in letters {
            count[$9,$8] += $7
            seen[$8]
        }
        END { 
            print FILENAME
            for (i in seen) {
                sum = 0
                for (j=1; j<=4; j++) {
                    print i, letter[j], count[letter[j],i]
                    sum += count[letter[j],i]
                }
                print i, "T", count["T",i], (count["T",i] == sum ? "ERROR" : "MATCHED")
            } 
        }
    ' "$f"
done > output.csv

即使没有gawk,您也可以连同其他一些调整,将该结束块放入函数中,并在
FNR==1
END
条件下调用它,这样您就不需要shell循环了<代码>结束文件出现在gawk 4.0 btw中,请参见。重写成功,最终我将更新为类似的内容,但现在我只是使用变量$fname进行调整,并在每个循环之前打印。还删除了临时文件和cat。多谢各位。
gawk -F '\x01' -v OFS="|" '
    BEGIN {...}
    FNR == 1 {next}
    $9 in letters {...}
    ENDFILE {
        print FILENAME
        for ...
        # clean up the counters for the next file
        delete count
        delete seen
    }
' ./* > output.csv