2

本网站的新手和一般编程(生物学家背景)。

无论如何,我的任务是获取文本文件名,计算唯一行数,计算总行数并将其输出到 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. 有没有更有效的方法将输出添加到输出文件?

谢谢!

弗兰

4

2 回答 2

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仔细设置环境变量name、清空字符串unique然后total运行命令——这并不完全是错误的,但也不是你想的那样。sort | uniq可以简化sort -u为。不需要cat $file | wc -lwhenwc -l < $file用更少的流程来完成同样的工作。该ls行正在生成与通配符扩展相同的名称。一次一个文件与所有文件一起存在一些问题。

如果您想要一个 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"

唯一可能的缺点是它对每个文件运行一次命令,如果有很多文件,这可能会有点问题。然而,这会奏效——先把它做好,然后,如果有速度问题,花时间优化它。

于 2013-09-18T05:54:13.170 回答
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以查看它是否已经安装,如果是,它在您的系统上的位置。

于 2013-09-18T07:50:10.907 回答