【问题标题】:Group files and pipe to awk command分组文件和管道到 awk 命令
【发布时间】:2012-05-02 23:36:57
【问题描述】:

我在一个目录中有文件;它们使用 YYYY_MM_DD 命名:

-rw-r--r-- 1 root root 497186 Apr 21 13:17 2012_03_25
-rw-r--r-- 1 root root 490558 Apr 21 13:17 2012_03_26
-rw-r--r-- 1 root root 488797 Apr 21 13:17 2012_03_27
-rw-r--r-- 1 root root 316290 Apr 21 13:17 2012_03_28
-rw-r--r-- 1 root root 490081 Apr 21 13:17 2012_03_29
-rw-r--r-- 1 root root 486621 Apr 21 13:17 2012_03_30
-rw-r--r-- 1 root root 490904 Apr 21 13:17 2012_03_31
-rw-r--r-- 1 root root 491788 Apr 21 13:17 2012_04_01
-rw-r--r-- 1 root root 488630 Apr 21 13:17 2012_04_02

文件中的第一列是一个数字,我使用以下awk 命令取第一列的平均值。

awk -F, '{ x += $1 } END { print x/NR }' MyFile

使用相同的命令,我可以将两个文件传递给 awk 以获得两个文件作为一个整体的总平均值。

awk -F, '{ x += $1 } END { print x/NR }' File1 File2

我想做的是这个……

我想获取我目录中的所有文件,并每月对它们进行分组,然后将当月的所有文件传递给 awk 命令。

因此,根据相同的数据,3 月份有 7 个文件,我希望所有 7 个文件都传递给我的 awk 命令,如下所示:

awk -F, '{ x += $1 } END { print x/NR }' File1 File2 File3 File4 File5 File6 File7

那么对于四月的系列也是如此。

【问题讨论】:

  • 您将如何决定应该处理哪些月份?会不会是类似monthly_stats 2012-03 2012-04 的命令调用?或者您是否需要扫描目录中的所有文件以查看代表的月份以便处理所有文件?

标签: linux bash awk xargs


【解决方案1】:

您是想以某种方式单独使用 awk 来完成此任务,还是可以使用文件通配符?例如:

awk -F, '{ #Do stuff }' 2012_03_[0-3][0-9]

将获取所有 March 文件。

您也可以使用2012_03*,但它的通配模式不如上述具体。

编辑

您可以使用这样的 shell 脚本:

DIR="/tmp/tmp"
for month in $(find "$DIR" -maxdepth 1 -type f | sed 's/.*\/\([0-9]\{4\}_[0-9]\{2\}\).*/\1/' | sort -u); do
  awk -F, '#dostuff' "$DIR/${month}"_[0-3][0-9] > output/dir/SUM_"${month}"
done

与往常一样,有一些注意事项。带有空格的文件会破坏它。如果目录中存在不符合 YYYY_MM_DD 格式的文件,则会出现错误,但不会影响性能。让我知道这些限制是否不可接受,我会再考虑一下。

【讨论】:

  • 这没关系,但我只想指向目录,让它计算出有多少个月,如果你理解我的话,每个月作为一个批次处理。这里也有很多年,所以可能存在 2012_04_11 和 2011_04_11。
  • 是的,应该没问题,有时间我会玩一玩,让你知道。谢谢。
  • 我会赞成你答案的第一部分,但添加的部分使用for ... in $(ls)(两次,不少于)。此外,ls 的输出将包括您未能剥离的目录 - 因此在您的示例中,year 将等于“路径”。说到“不太具体”,您可以使用2012_03_[0-3][0-9]稍微更具体一些。
  • @DennisWilliamson 好点。我之前有点粗心。请参阅我编辑的答案。
【解决方案2】:

在 Perl 中你可以这样做:

#!/usr/bin/env perl
$dir = shift || ".";
opendir(DIR, $dir);
@files=grep (/\d{4}_\d{2}_\d{2}/, readdir(DIR));

foreach $file (@files)
{
    ($year_month) = $file =~ /(\d{4}_\d{2})/;
    open(FILE, "<$dir/$file");
    while($col = <FILE>)
    {
        $col =~ s/^(\d*)/\1/;
        if($col)
        {
            $hash{"$year_month"}{"count"}++;
            $hash{"$year_month"}{"sum"} += $col;
        }
    }
}

foreach $year_month (keys %hash)
{
    $avg = $hash{"$year_month"}{"sum"} / $hash{"$year_month"}{"count"};
    print "$year_month : $avg\n";
}

可能可以做得更短,但这样你就有一个很好的哈希数据结构,以防你以后想以不同的方式计算它。像这样调用:

script.pl /path/to/dir

编辑:错误:忘记将目录添加到路径

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-15
    • 1970-01-01
    • 1970-01-01
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多