【问题标题】:How to use awk on multiple files?如何在多个文件上使用 awk?
【发布时间】:2020-02-04 14:01:24
【问题描述】:

我正在使用 Linux。我写了一些看起来像这样的代码:

for x in {10..20}:{00..59}; do awk -F';' '/'"$x"'/ {y+=$7} END {print y}' Data26092019; done

如何对多个文件使用此命令,例如:Data26092019 和 Data27092019?

文件是这样的:

09:55:13;ACSEL;4.850;16;77.60;1;1
09:55:13;ACSEL;4.850;40;194.00;2;1
09:55:13;ACSEL;4.850;465;2255.25;3;1
...

输出示例:

Data26092019 4988 10:00
Data26092019 2778 10:01
...
Data27092019 3252 10:00
Data27092019 3002 10:01

也许它应该与另一个 for 循环一起使用,或者您可以指定文件。

主要命令是:

for x in {10..20}:{00..59}; do awk -F';' '/'"$x"'/ {y+=$7} END {print y}' Data26092019; done

它必须在Data26092019Data27092019 上执行。

【问题讨论】:

  • awk -F';' '/'"$x"'/ {y+=$7} END {print y}' Data26092019 Data27092019?你想对这些文件做什么?
  • 我希望该命令对所有文件单独执行。
  • for all files seperate - 所以你想“遍历文件”并运行“针对每个文件”的命令。当然google.com/search?q=iterate+over+files+bash。您的命令看起来很慢 - 它处理同一个文件 120 次。创建一个长的 awk 命令并只处理一次文件可能是可取的并且真的更快。如果您只是每个第一列的第 7 列的总和,我认为没有必要遍历所有可能的值,awk 数组可以来救援。
  • 不要for x in {10..20}:{00..59};。你正在运行awk 120 次。运行一次。您的 awk 脚本看起来真的很像 awk '{ sum[$1]+=$7 } END{ foreach (i in sum) print i " " sum[i]; }。查看 ex stackoverflow.com/questions/42024296/… 了解有关此类主题的更多信息。
  • 我正在使用这个版本的命令,因为我希望所有分钟的总和分开。

标签: linux shell awk text-processing


【解决方案1】:

编辑: 如果您想使用 END(或没有 GNU awk)+ 您希望 sum 的顺序相同您正在传递 Input_files 然后尝试以下操作。

使用END

awk '
BEGIN{
 FS=";"
}
!filename[FILENAME]++{
  a[++count]=FILENAME
}
{
  sum[FILENAME]+=$7
}
END{
  for(i=1;i<=count;i++){
    print "Sum of minute for file: " a[i] " is: " sum[a[i]]
  }
}'  Data26092019 Data27092019


使用ENDFILE

请您尝试以下,未测试,因为 OP 没有提供样本。 需要 GNU awk

awk 'BEGIN{FS=";"} {sum+=$7} ENDFILE{print "Sum of minute for file: " FILENAME " is: " sum;sum=""}' Data26092019 Data27092019

【讨论】:

  • 第二个解决方案中哪里可以插入模式?
  • @User11221475,您要放在哪里或要检查哪个条件?一旦你澄清我可以为你写
  • @User11221475,你不能在 awk 变量中定义 shell 变量,你需要像这样:awk -v var="$shell_variable" '$0 ~ var' file 这样。
  • 代码:对于 {10..17} 中的时间:{00..59} 执行 awk ' BEGIN{ FS=";" } !filename[FILENAME]++{ a[++count]=FILENAME } { sum[FILENAME]+=$7 } END{ for(i=1;i
  • 这将跳过空文件,而不是用值 0 打印它们。
【解决方案2】:

简单地说,您可以执行以下操作:

for file in f1 f2 f3 f4; do
   for time in {10..20}:{00..59}; do 
      sum=$(awk -v t="${time}" -F";" '($0~"^"t){sum+=$7}END{print sum}' "$file"
      echo "$file $sum $time"
   done
done

但是,这非常慢,因为您在搜索特定时间键时会多次打开每个文件。

我相信你追求的是这个:

awk 'function print_summary(    h,m,key) {
        for (h=10;h<=20;++h) {
           for (m=0;m<60;++m) {
              key=sprintf("%0.2d:%0.2d",h,m)
              print fname, sum[key]+0, key
           }
        }
     }
     BEGIN{FS=";"}
     (FNR==1){if(NR>1) print_summary(); delete sum; fname=FILENAME}
     !/^..:..:../{next}
     { key=substr($0,1,5) }
     { sum[key]+=$7 }
     END { print_summary() }' file1 file2 file3 ...

此方法将跳过空文件,但会准确报告预期内容。

【讨论】:

  • 你说的太对了。我知道有这样一个快速的解决方案。
  • 这仅适用于一个文件。如果我写 Data26092019 和 Data27092019 程序只对第二个文件(最后一个给定)执行它。
  • 我在终端中以 .sh 文件的形式运行,命令为:'./Command.sh'
  • @User11221475 是的,我看到了问题,现在应该解决了。
【解决方案3】:

另一个:

$ awk -F\; '{
    sum[FILENAME]+=$7
} 
END {
    for(f in sum)
        print f,sum[f]
}' file1 file2

带有 2 个样本数据副本的输出:

file1 3
file2 3

【讨论】:

  • 非常感谢。它也有效。我认为这个解决方案更便携(常见)。
  • 这将跳过空文件,而不是用值 0 打印它们。
  • 是的,如果没有正确的样本数据结束预期输出,很难说。只是拿了 op 的代码来展示如何输出每个文件。
【解决方案4】:

使用 gawk,您可以调整@JamesBrown 的答案:

gawk -F\; '{
    sum += $7
} 
ENDFILE {
    print FILENAME, sum
    sum=0
}' file1 file2

【讨论】:

  • 恕我直言,我已经在很长一段时间内给出了这个解决方案stackoverflow.com/a/58267439/5866580
  • 如果第一个文件为空,这将打印一个空字符串而不是 0。
【解决方案5】:

非常感谢您的友好回答。我是新手,我无法理解和评论所有不同的解决方案。对我帮助最大的是 @kvantour 的功能解决方案。代码:

awk 'function print_summary(    h,m,key) {
        for (h=10;h<=20;++h) {
           for (m=0;m<60;++m) {
              key=sprintf("%0.2d:%0.2d",h,m)
              print fname, sum[key]+0, key
           }
        }
     }
     BEGIN{FS=";"}
     (FNR==1){if(NR>1) print_summary(); delete sum; fname=FILENAME}
     !/^..:..:../{next}
     { key=substr($0,1,5) }
     { sum[key]+=$7 }
     END { print_summary() }' file1 file2 file3 ...

【讨论】:

  • 不要担心是这个论坛的新手。我们都去过那里。如果您有任何问题,请在下面的 cmets 中提问,我们将尽力解答。另外,作为一个新人,拿tour阅读How to Ask总是好的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-06
  • 1970-01-01
  • 1970-01-01
  • 2016-07-12
  • 2015-01-18
  • 1970-01-01
相关资源
最近更新 更多