Awk 找到第一个匹配项后匹配特定模式,并在它们之间关联列

Awk 找到第一个匹配项后匹配特定模式,并在它们之间关联列,awk,Awk,我需要找出文件中不共享公共标识符的两个相关行之间的时间戳差异。例如: 正文 2018-01-29 15:05:11592验证控制 正文 正文 正文 2018-01-29 15:05:12725完成验证控制 由于每个验证过程都没有唯一的标识符,因此我需要: 首先将一行与“正在验证控制…”匹配 将时间戳保存到数组中 匹配文件中包含“已完成验证控件”的下一行 保存时间戳 我有一个计算时间差的函数——我有一段艰难的时光 分析并关联每两个验证/已完成验证行。虽然每一行都有数百行,但它们总是按顺序出现,并按

我需要找出文件中不共享公共标识符的两个相关行之间的时间戳差异。例如:

  • 正文
  • 2018-01-29 15:05:11592验证控制
  • 正文
  • 正文
  • 正文
  • 2018-01-29 15:05:12725完成验证控制
  • 由于每个验证过程都没有唯一的标识符,因此我需要:

  • 首先将一行与“正在验证控制…”匹配
  • 将时间戳保存到数组中
  • 匹配文件中包含“已完成验证控件”的下一行
  • 保存时间戳
  • 我有一个计算时间差的函数——我有一段艰难的时光 分析并关联每两个验证/已完成验证行。虽然每一行都有数百行,但它们总是按顺序出现,并按顺序处理。因此,我始终知道,当我找到“验证”时,下一次出现的“完成验证”(无论向下多远)将与之对应

    我在想我可以独立地解析出所有行(所有“验证”到文件A中,所有“完成验证”到文件B中),然后逐行关联。这是最好的方法吗?或者有没有一种方法可以在不生成其他文件的情况下执行此操作?

    使用bash:

    #!/bin/bash
    
    while read -r a b c d e; do
      [[ "$c $d" =~ Validating\ control... ]] && echo "$a $b"
      [[ "$c $d $e" =~ Done\ validating\ control. ]] && echo "$a $b"
    done < file
    
    #/bin/bash
    而read-ra-b-c-d-e;做
    [[“$c$d”=~验证\控制…]&&echo“$a$b”
    [[“$c$d$e”=~Done\validating\control.]&&echo“$a$b”
    完成<文件
    

    #/bin/bash
    而read-ra-b-c-d-e;做
    [[“$c$d”=~验证\控制…]&&start=“$a$b”
    如果[[“$c$d$e”=~完成\验证\控制。]];然后
    stop=“$a$b”
    回显“$start”
    回音“$stop”
    fi
    完成<文件
    
    输出:

    2018-01-29 15:05:11,592 2018-01-29 15:05:10,725
    $ ./test.sh
    arr1: 2018-01-29 15:05:11,592 2018-01-29 15:10:11,592 2018-01-29 15:15:11,592
    arr2: 2018-01-29 15:05:10,725 2018-01-29 15:10:10,725 2018-01-29 15:15:11,725
    
    2018-01-29 15:05:11,592 2018-01-29 15:05:10,725 对于bash:

    #!/bin/bash
    
    while read -r a b c d e; do
      [[ "$c $d" =~ Validating\ control... ]] && echo "$a $b"
      [[ "$c $d $e" =~ Done\ validating\ control. ]] && echo "$a $b"
    done < file
    
    #/bin/bash
    而read-ra-b-c-d-e;做
    [[“$c$d”=~验证\控制…]&&echo“$a$b”
    [[“$c$d$e”=~Done\validating\control.]&&echo“$a$b”
    完成<文件
    

    #/bin/bash
    而read-ra-b-c-d-e;做
    [[“$c$d”=~验证\控制…]&&start=“$a$b”
    如果[[“$c$d$e”=~完成\验证\控制。]];然后
    stop=“$a$b”
    回显“$start”
    回音“$stop”
    fi
    完成<文件
    
    输出:

    2018-01-29 15:05:11,592 2018-01-29 15:05:10,725
    $ ./test.sh
    arr1: 2018-01-29 15:05:11,592 2018-01-29 15:10:11,592 2018-01-29 15:15:11,592
    arr2: 2018-01-29 15:05:10,725 2018-01-29 15:10:10,725 2018-01-29 15:15:11,725
    
    2018-01-29 15:05:11,592 2018-01-29 15:05:10,725
    这是GNU awk中的一个,它也计算时间差。示例运行两次相同的数据:

    $ awk '
    BEGIN { FS="[- :,]" }          # set FS to get the timestamp parts
    /alidating/ {                  # if matched
        if(a!="") {                # read the latter value and convert to epoch time:
            b=mktime($1 " " $2 " " $3 " " $4 " " $5 " " $6)+($7/10^length($7))
            print b-a              # calculate time difference
            a=b=""                 # reset vars for the next pair
            next                   # skip to next record
        }                          # below the former of two values is processed:
        a=mktime($1 " " $2 " " $3 " " $4 " " $5 " " $6)+($7/(10^length($7)))
    }' file file                   # use same test data twice
    0.867
    0.867
    

    +($7/10^length($7))
    处理分数部分,例如0592将被转换为592/10^3=592/1000=0.592,0,1将转换为1/10=0.1,依此类推。

    这里是GNU awk中的一个,它也计算时间差。示例运行两次相同的数据:

    $ awk '
    BEGIN { FS="[- :,]" }          # set FS to get the timestamp parts
    /alidating/ {                  # if matched
        if(a!="") {                # read the latter value and convert to epoch time:
            b=mktime($1 " " $2 " " $3 " " $4 " " $5 " " $6)+($7/10^length($7))
            print b-a              # calculate time difference
            a=b=""                 # reset vars for the next pair
            next                   # skip to next record
        }                          # below the former of two values is processed:
        a=mktime($1 " " $2 " " $3 " " $4 " " $5 " " $6)+($7/(10^length($7)))
    }' file file                   # use same test data twice
    0.867
    0.867
    

    +($7/10^length($7))
    处理分数部分,例如0592将转换为592/10^3=592/1000=0.592,0,1将转换为1/10=0.1,依此类推。

    awk
    用于救援

    从匹配的行创建时间戳对

    $ awk 'BEGIN                    {FS=OFS=","} 
           /Validating control/     {s=$1} 
           /Done validating control/{print s,$1}' file
    
    2018-01-29 15:05:11,2018-01-29 15:05:10
    
    也许在
    awk
    中包含时间增量计算也是有意义的

     $ awk 'BEGIN                   {FS=OFS=","} 
           /Validating control/     {s=$1} 
           /Done validating control/{gsub(/[:-]/," ",s); 
                                     gsub(/[:-]/," ",$1); 
                                     print mktime($1)-mktime(s)}' file
    
    但是,您的数据处于反向时间(在开始前1秒结束),因此结果将为负秒

    如果秒后的数字是时间戳的一部分,这可能会更好

    $ awk -F'[, ]' '/Validating control/{s=$1":"$2;ms=$3} 
               /Done validating control/{t=$1":"$2; 
                                         print s ms,t $3; 
                                         gsub(/[:-]/," ",s); 
                                         gsub(/[:-]/," ",t); 
                                         print (mktime(t)+($3/1000))-(mktime(s)+(ms/1000))}' file
    
    2018-01-29:15:05:11592 2018-01-29:15:05:10725
    -0.867
    

    awk
    救援

    从匹配的行创建时间戳对

    $ awk 'BEGIN                    {FS=OFS=","} 
           /Validating control/     {s=$1} 
           /Done validating control/{print s,$1}' file
    
    2018-01-29 15:05:11,2018-01-29 15:05:10
    
    也许在
    awk
    中包含时间增量计算也是有意义的

     $ awk 'BEGIN                   {FS=OFS=","} 
           /Validating control/     {s=$1} 
           /Done validating control/{gsub(/[:-]/," ",s); 
                                     gsub(/[:-]/," ",$1); 
                                     print mktime($1)-mktime(s)}' file
    
    但是,您的数据处于反向时间(在开始前1秒结束),因此结果将为负秒

    如果秒后的数字是时间戳的一部分,这可能会更好

    $ awk -F'[, ]' '/Validating control/{s=$1":"$2;ms=$3} 
               /Done validating control/{t=$1":"$2; 
                                         print s ms,t $3; 
                                         gsub(/[:-]/," ",s); 
                                         gsub(/[:-]/," ",t); 
                                         print (mktime(t)+($3/1000))-(mktime(s)+(ms/1000))}' file
    
    2018-01-29:15:05:11592 2018-01-29:15:05:10725
    -0.867
    

    下面显示了一个脚本,您可以在其中将输出保存到
    bash
    中的数组中

    $ cat test.sh
    #!/bin/bash
    
    # Use sed to print only the relevant lines.
    # This also reduces the number of lines to be processed by while loop
    sed -n '/Validating control.../,/Done validating control/{//p}' inputFile.txt > /tmp/input_sedVersion.txt
    
    declare -a arr1=()
    declare -a arr2=()
    i=0
    while read -r _date _time _state
    do
        if [[ "$_state" =~ Validating ]]; then
        arr1[$i]="$_date $_time";
        else
        arr2[$i]="$_date $_time";
        ((i++));
        fi
    done < /tmp/input_sedVersion.txt
    
    echo "arr1: ${arr1[@]}"
    echo "arr2: ${arr2[@]}"
    
    # Code do something with these arrays
    

    下面显示了一个脚本,您可以在其中将输出保存到
    bash
    中的数组中

    $ cat test.sh
    #!/bin/bash
    
    # Use sed to print only the relevant lines.
    # This also reduces the number of lines to be processed by while loop
    sed -n '/Validating control.../,/Done validating control/{//p}' inputFile.txt > /tmp/input_sedVersion.txt
    
    declare -a arr1=()
    declare -a arr2=()
    i=0
    while read -r _date _time _state
    do
        if [[ "$_state" =~ Validating ]]; then
        arr1[$i]="$_date $_time";
        else
        arr2[$i]="$_date $_time";
        ((i++));
        fi
    done < /tmp/input_sedVersion.txt
    
    echo "arr1: ${arr1[@]}"
    echo "arr2: ${arr2[@]}"
    
    # Code do something with these arrays
    

    我忽略了这个问题只标记为“awk”。但是它可能会对awk有所帮助/已完成验证控件。/{stop=$1fs$2}END{print start;print stop}文件Btw:with GNU sed:
    sed-En的/^([^]+[^]+)(验证控件…|已完成验证控件。)/\1/p'文件
    没有问题。我之所以选择awk,是因为我的原始脚本就是这样使用的,但是如果它完成了任务,并且可以集成到脚本中,我就不会有任何问题。不过Bash解决方案很好。将首先尝试awk建议,看看什么最有效。谢谢!:)我忽略了这个问题只标记为“awk”。但是它可能会对awk有所帮助/已完成验证控件。/{stop=$1fs$2}END{print start;print stop}文件Btw:with GNU sed:
    sed-En的/^([^]+[^]+)(验证控件…|已完成验证控件。)/\1/p'文件
    没有问题。我之所以选择awk,是因为我的原始脚本就是这样使用的,但是如果它完成了任务,并且可以集成到脚本中,我就不会有任何问题。不过Bash解决方案很好。将首先尝试awk建议,看看什么最有效。谢谢!:)它必须与awk一起使用吗?输入文件有多大?最好使用awk,是的,因为我正在集成到一个更大的awk脚本中,该脚本可以解析从几Mb到~3 Gb的任意位置的日志。但是我可以在Awk脚本中调用bash/sh,这样可以证明它更有效。明白了。我添加了一个bash脚本。希望能有帮助。是否一定要使用
    awk
    ?输入文件有多大?最好使用awk,是的,因为我正在集成到一个更大的awk脚本中,该脚本可以解析从几Mb到~3 Gb的任意位置的日志。但是我可以在Awk脚本中调用bash/sh,这样可以证明它更有效。明白了。我添加了一个bash脚本。希望有帮助。谢谢你指出这一点。我一定是抄了mi之前的一行