【问题标题】:Using AWK to process two different files consecutively使用AWK连续处理两个不同的文件
【发布时间】:2014-01-22 10:57:14
【问题描述】:

我正在尝试使用 awk 连续评估两个文件。在第一个文件的末尾,我正在读取一个日期,并将该日期用作评估第二个文件的输入。不幸的是,我在理解如何检测第一个文件的结尾读取日期并继续评估下一个文件时遇到了一些问题。我找到了一些答案,例如 FNR==NR,不幸的是,我无法正确实现它们。我通过硬编码行数来尝试穷人的解决方案。然而,这并不是一件非常聪明的事情。我在处理第二个文件时仍然遇到问题:

    BEGIN initalize the counters 



    {
    if(NR==FNR) <<<<<< this is needed to run properly, only NR==FNR fails, why ?!       
    {     
          # file_1      
          do -> from the last line of the first file extract a date 

          next << what is the meaning of this ??
    }                        

    {
          # file_2
          do -> read every line of the second file 
             and sum up the values form one of the colums


    }


    }


    END { divide the sum accumulated form file=2 
          by the time calculated form the last line of file=1}

# for calling the script use :
awk -f SCRIPT file_1 file_2

#example files
# file1 last line
version 1.5 code 11 mpi start /01/12/2014/ 18:33:12 end /01/12/2014/ 20:05:12

#file2

     1.28371E-05    0.2060    0.2060   -8   -8    0    0    0
     1.91616E-05    0.1927    0.1927   -7   -8    0    0    0
     1.27306E-05    0.1567    0.1567   -6   -8    0    0    0
     2.11623E-05    0.1523    0.1523   -5   -8    0    0    0
     1.67914E-05    0.1721    0.1721   -4   -8    0    0    0
     1.47247E-05    0.1851    0.1851   -3   -8    0    0    0
     1.32049E-05    0.1919    0.1919   -2   -8    0    0    0
     1.81256E-05    0.2130    0.2130   -1   -8    0    0    0
     2.63500E-05    0.1745    0.1745    0   -8    0    0    0
     1.99232E-05    0.1592    0.1592    1   -8    0    0    0
     2.08924E-05    0.1537    0.1537    2   -8    0    0    0
     2.44922E-05    0.1459    0.1459    3   -8    0    0    0
     2.53759E-05    0.1902    0.1902    4   -8    0    0    0
     2.30230E-05    0.1708    0.1708    5   -8    0    0    0
     2.10723E-05    0.1636    0.1636    6   -8    0    0    0
     1.86613E-05    0.1915    0.1915    7   -8    0    0    0
     2.05359E-05    0.1649    0.1649    8   -8    0    0    0
     1.09533E-05    0.1765    0.1765   -8   -7    0    0    0
     1.56917E-05    0.1740    0.1740   -7   -7    0    0    0
     1.52199E-05    0.2145    0.2145   -6   -7    0    0    0
     .....   

如果有任何帮助,我将不胜感激, 提前谢谢你

亚历克斯

【问题讨论】:

  • 听起来你想要的在 awk 中绝对是微不足道的,但请澄清At the end of the first file I am reading a date 的意思,因为有几种可能性,例如您正在从文件中读取它(在这种情况下,为什么不在脚本运行之前执行它)或从变量中获取它(同上)或提示某人输入它或其他内容,适合您的解决方案取决于它是什么你正在这一步做。
  • 对于给您带来的不便,我深表歉意。我正在阅读一个文件,比如文件 A。这个文件的末尾包含日期和时间。我读了这段时间,然后继续阅读第二个文件,在那里我将时间用作某些表达式的输入。所以说从第一个文件中提取一个变量,其值用于处理第二个文件。
  • 我在回答中发布了,看看这是否就是你所需要的。如果没有,请发布一个脚本来演示您的问题以及一些示例输入和预期输出。您发布的脚本似乎有很多复杂性,与您描述的问题完全无关,因此如果我们不必通读所有这些内容来查看实际问题,它会帮助我们为您提供帮助。跨度>
  • 如何将文件传递给 awk?如果你做了awk -f script.awk file1 file2 甚至cat file1 | awk -f script.awk - file2, FNR`,那么每个文件的第一条记录都会是 1。在FNR!=NR&amp;&amp;FNR==1 的情况下,您更改了文件,最后读取的记录将是您查找的日期。但是,如果您执行cat file1 file2 | awk -f script.awk,则 FNR!=NR` 永远不会为真,因为标准输入是单个文件,而 awk 将从该文件读取。
  • ...仍然没有预期的输出。叹息....

标签: awk end-of-life


【解决方案1】:

听起来你只需要这样的东西:

awk '
NR==FNR {
   do file1 stuff
   date = $0
   next
}
{
   do file2 stuff using the variable "date" which is set to the last line of file1
}
' file1 file2

如果这不是您所需要的全部,请发布一些示例输入和预期输出,以帮助阐明您要做什么。

【讨论】:

  • 我尝试简化我的示例代码,以便我的问题变得更容易理解。实际上,如果我正确理解您的想法,NR==FNR 可以确保我只阅读第一个文件。因为对于第一个文件,本地计数器 FNR 和全局计数器 NR 是相等的。对于第二个文件,它们按第一个文件的行数移动。但是如何准确检测第一个文件的结尾?
  • 在 gawk 中你可以使用 ENDFILE 但到目前为止我还没有看到任何迹象表明你需要它。在我发布的示例中,在读取 file2 和 END 部分时,变量 date 将填充第一个文件最后一行的值。那么,为什么这不是您所需要的全部?
  • 嗨 Ed,我认为你的想法没问题,当我将 NR==FNR 更改为 if 语句 if(NR==FNR) 我不知道为什么时,问题就消失了。此外,“下一步”到底在做什么?
  • 您不需要将 NR==FNR 更改为 if 语句,而是需要删除您错误地添加到脚本中的开头 { 和关闭 }。另外 - 不要在 NR==FNR{ 之间添加换行符 - 空格对 awk 很重要。 next 告诉 awk 读取下一条记录,而不是继续处理当前记录。
【解决方案2】:

您可以通过以下几种方式做到这一点:

  • 缓冲每一行并检查何时FNR==1

类似:

awk 'FNR==1 && NR!=1{print line,"is last in first file"}NR>1{print line}{line=$0} '
  • 如果您使用的是gawk,则可以使用ENDFILE 块。

或者:

gawk '{print $0} ENDFILE && !f {print $0,"is last line in first file", f=1}'

【讨论】:

  • 您好,感谢您的帮助。可悲的是,它没有按预期工作,代码最终在屏幕上打印了整个文件。我也尝试按照您的建议修改我的脚本,但无济于事。
【解决方案3】:

我在命令行上设置变量来完成这个:

awk 'F==1 {print "one: ", $0} F==2 {print "two: ", $0}' F=1 one.txt F=2 two.txt

每当遇到 x=y 形式的东西时,它会将 awk 中的变量 x 设置为 y。

【讨论】:

  • 您好,我已经更新了我的脚本。实际上,您提出的建议以某种方式朝着正确的方向发展。表达式 F==1 F==2 确保我正在读取正确的文件。但是我如何检测第一个文件的结尾。我可以使用正则表达式(F==1 && /regex/),但是,我认为存在更优雅的解决方案。
  • 在 Gnu Awk 中有一个 ENDFILE{} 规则。所以你可以试试 ENDFILE { if (FNR==NR) date=$0 }
  • @AlexanderCska 你真的需要知道最后一行吗?你不能在第一个文件的块中保留一个变量lastLineFile1 = $0,然后在END 子句中从lastLineFile1 中提取你需要的日期/时间吗?
【解决方案4】:

如果你只想要第一个文件最后一行的日期和第二个文件的内容供 awk 处理,你可以这样做,让生活更轻松:

(tail -1 firstfile; cat secondfile ) | awk 'something' -

当然,如果日期不是最后一行,你可以这样做:

(grep ^Date firstfile; cat secondfile ) | awk 'something' -

这样,在 awk 中您将只需要处理一个“文件/流”,并且第一行将是您的日期。

【讨论】:

    猜你喜欢
    • 2021-10-02
    • 1970-01-01
    • 2012-10-26
    • 1970-01-01
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多