将值输出到csvs - 命令行

时间:2013-09-18 02:54:41

标签: bash csv command-line

此网站的新功能和一般编程(生物学家的背景)。

无论如何,我有一个任务是获取文本文件名,计算唯一行,计算总行数并将其输出到csv文件中。这是我在Cygwin中使用的代码

#!/bin/bash
file=./data/*.txt
name= ls ./data > output.csv
unique= sort $file | uniq | wc -l >> output.csv
total= cat $file | wc -l >> output.csv
nano output.csv

我得到了所有正确的输出,我的问题是:

  1. 我可以选择输入每个值的列吗?目前,它们直接相互添加。

  2. 是否有更有效的方法将输出添加到输出文件?

  3. 谢谢!

    弗兰

2 个答案:

答案 0 :(得分:3)

现有代码有许多改进,包括:

#!/bin/bash
file=./data/*.txt
name= ls ./data > output.csv
unique= sort $file | uniq | wc -l >> output.csv
total= cat $file | wc -l >> output.csv
nano output.csv

写入output.csv的三行仔细设置环境变量nameuniquetotal以清空字符串,然后运行命令 - 这不是错误的,但你真的不是想到的。 sort | uniq可以简化为sort -u。当cat $file | wc -l只用少一个进程执行相同的工作时,不需要wc -l < $filels行生成的名称与通配符扩展名称相同。你一次有一个文件与所有文件一起出现问题。

如果您想要一个包含每个文件的名称,唯一行和总行的CSV文件,那么我们希望在代码中看到一个循环。

for file in ./data/*.txt
do
    unique=$(sort -u $file | wc -l)
    total=$(wc -l < $file)
    echo "$file,$unique,$total"
done

运行sort -u以唯一排序(不需要显式uniq),并捕获wc -l的输出。它运行wc -l,其文件的标准输入为总行数;使用I / O重定向停止wc打印文件名。然后回声打印数据。如果您只想要文件的基本名称(仅xyz.txt而不是./data/xyz.txt),那么您可以在echo中修复此问题:

echo "$(basename $file),$unique,$total"

或:

echo "${file##*/},$unique,$total"

唯一可能的缺点是它每个文件运行一次命令,如果有很多文件,这可能会有点问题。但是,这将起作用 - 首先正确,只有在遇到速度问题时才花时间进行优化。

答案 1 :(得分:2)

没有人可以与Jonathan Leffler竞争,但以下gawk脚本也可以处理您的要求。这是一个更多的代码,但在多个文件的情况下,它可能比shell脚本更有效。

#!/usr/local/bin/gawk -f

function show() {
  print last,length(unique),total;
  last=FILENAME;
  delete(unique);
  total=0;
}

BEGIN {
  OFS=",";
}

NR==1 {
  last=FILENAME;
}

FILENAME != last {
  show();
}

{
  total++; unique[$0];
}

END {
  show();
}

这里唯一新颖的事情是使用unique[]数组。由于awk的数组都是关联的,因此使用$0作为键会产生一个数组,其长度是唯一行的数量。仅仅引用数组元素会导致它存在,因此您实际上不需要 unique[$0]设置为任何内容。

要使用该脚本,您可以使用如下命令行:

$ ./script.sh one.txt two.txt > output.csv

或者像

这样的东西
$ ./script.sh *.txt > output.csv

请注意,在Cygwin中,您可能需要显式安装gawk包,并且需要在脚本的第一行调整gawk的路径。您可以键入which gawk以查看它是否已安装,如果已安装,则可以在系统上的位置。