【问题标题】:Running find, grep and awk script运行 find、grep 和 awk 脚本
【发布时间】:2020-05-19 23:26:32
【问题描述】:

我正在使用 find 来搜索文件。然后我将此文件作为 grep 的参数传递。我想在每个结果上运行 awk 脚本?我该怎么做?

可以这么说,find 返回 5 个文件,每个文件上的 grep 返回 15 行,在这 15 行上,我想运行 awk 脚本。

我试过了,但是出错了

find . -type f -name test.log | xargs grep -A 15 "Data starts now" | xargs awk -f postprocess.awk

任何人都可以建议语法有什么问题吗?

假设文件 test1.log 是

num1 104
num2 434
Num3 572
Data starts now
num1 04
num2 34
Num3 72

假设文件 test2.log 是

num1 203
num2 135
Num3 098
Data starts now
num1 17
num2 33
Num3 89

假设文件 test3.log 是

num1 924
num2 834
Num3 532
Data starts now
num1 34
num2 63
Num3 89

postprocess.awk 是

{
if($1=="num1")
   {
   num1_value =$2;
   }

if($1=="num2")
   {
   num2_value =$2;
   }


if($1=="num3")
   {
   num3_value =$2;
   }



}

END {
mult=num1_value*num2_value;
print "Multiplication is " mult;
}

如果我跑

find . -type f -name "test*.log" -exec grep -A15 "Data starts now" {} + | awk -f postprocess.awk

我应该得到 3 个输出,但只得到 1 行错误的结果

Multiplication is 0

【问题讨论】:

  • 我提供了this answer,它使用 GNU awk 完成一切

标签: linux awk


【解决方案1】:

如果您有 GNU awk,您可以在一行中完成所有操作

$ awk 'c{c--;a[$1]=$2} /Data starts now/{c=15} \
    ENDFILE{m=1;c=0;for(i in a){m*=a[i]}print FILENAME": Multiplication is "m}' test*.log
test1.log: Multiplication is 9792
test2.log: Multiplication is 49929
test3.log: Multiplication is 190638

说明

awk '
  c{                       # if c is non-zero (c is 0 when script is 1st ran)
     c--                   # decrement c
     a[$1]=$2              # Create a hash-map with $1 as the key and $2 as the value
   }
  /Data starts now/{c=15}  # When regex matches, set c to 15
  ENDFILE{                 # True when the last record of a file has been read (gawk only)
    m=1                    # Set m to one so multiplication doesnt return 0
    c=0                    # Set c to 0 in case file has less than 15 lines after match
    for(i in a){           # For each key/value pair...
      m*=a[i]              # Multiply them together and store result in m
    }
    print FILENAME": Multiplication is "m}
' test*.log

【讨论】:

    【解决方案2】:

    要对find 找到的每个单独文件运行grepawk,您可以使用-exec 操作并启动一个小shell 脚本:

    find . -type f -name "test*.log" -exec sh -c '
      for file; do
        grep -A15 "Data starts now" "$file" | awk -f postprocess.awk
      done
    ' sh {} +
    

    【讨论】:

    • 上述解决方案不起作用..它只产生 1 个输出,这太错误了。我正在使用 Cshell
    【解决方案3】:

    如果你创建另一个帮助脚本(postprocess.sh)会更清楚

    for f in $*
    do
       grep -A 15 "Data starts now" $f | awk -f postprocess.awk
    done
    

    然后在 -exec: 中运行它:

    find . -type f -name "test*.log" -exec sh postprocess.sh {} +
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-28
      • 2019-05-14
      • 1970-01-01
      • 2013-03-13
      • 2022-06-15
      • 2022-01-03
      • 2021-11-29
      相关资源
      最近更新 更多