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

  • 本文关键字:关联 之间 第一个 模式 awk
  • 更新时间 :
  • 英文 :


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

  1. 发短信
  2. 2018-01-29 15:05:11,592 验证控制...
  3. 发短信
  4. 发短信
  5. 发短信
  6. 2018-01-29 15:05:12,725 完成验证控制。

由于每个验证过程都没有唯一标识符,因此我需要:

  1. 首先将一行与"正在验证控件...">
  2. 将时间戳保存到数组
  3. 匹配文件中包含"完成验证控制"的下一行。
  4. 保存时间戳

我有一个计算时间差异的功能 - 我遇到了困难 解析并关联每个验证/完成验证行。尽管每行将有数百行,但它们始终按顺序出现并按顺序处理。所以我总是知道,当我找到"验证"时,下一次出现的"完成验证"(无论多远)都会与之相对应。

我想我可以解析出彼此独立的所有行(所有"验证"到文件 A 中,所有"完成验证"到文件 B 中),然后逐行关联。这是最好的方法,还是有没有办法在不生成其他文件的情况下做到这一点?

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

但是,您的数据处于相反的时间(在开始前一秒结束),因此结果将是负秒。

如果秒后面的数字是时间戳的一部分,也许这会更好

$ 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:

#!/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
while read -r a b c d e; do
[[ "$c $d" =~ Validating control... ]] && start="$a $b"
if [[ "$c $d $e" =~ Done validating control. ]]; then
stop="$a $b"
echo "$start"
echo "$stop"
fi
done < file

输出:

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))处理分数部分,例如 0,592 将转换为 592/10^3 = 592/1000 = 0.592,0,1 将转换 1/10 = 0.1,依此类推。

下面显示了一个脚本,您可以在其中将输出保存到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

输出:

$ ./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

最新更新