使用grep

时间:2015-09-24 01:47:10

标签: regex linux bash shell

我有一个(GNU)bash脚本,它建立了两个要在文件中匹配的变量。

hour=$(head -n 1 sensorstest.log | cut -f5 | cut -d"-" -f1)
dom=$(head -n 1 sensorstest.log | cut -f5 | cut -d"-" -f4)

...并将它们与文件中的其他匹配项匹配

grep -E [^0-9]+"$hour"-[0-9]+-[0-9]+-"$dom"-[0-9]+-[0-9]{4} sensorstest.log

下面是一个脚本示例,用于计算给定时段内输入文件的字段2中所有值的均值。

hMean=$(grep -E [^0-9]+"$hour"-[0-9]+-[0-9]+-"$dom"-[0-9]+-[0-9]{4} sensorstest.log | cut -f2 | awk ' {sum+=$
1}{count++}{mean=sum/count} END {printf("%.2f",mean) } ' );

以下是清理输入文件的示例。

echo "removing: "$hour"th hour of the "$dom"th day  of the "$month"th month"
sed -i -r '/'"$hour"'-[0-9]+-[0-9]+-'"$dom"'-'"$month"'-[0-9]{4}/d' sensorstest.log

最后......这是文件中的示例行:

格式为:

status< tab> humidity< tab> temperature< tab> unix timestamp< tab> time / date

  

OK 94.4 16.9 1443058486 1-34-46-24-9-2015

我正在尝试匹配文件中第一个条目的的所有小时实例。

这适用于9以下的数字,但是;

问题:超过9的数字被匹配为两个单位数字,导致12个匹配1,2,12,21 ......等。

以下是出行的示例:

  

OK 100 17.2 1442570381 9-59-41-18-9-2015

     

OK 100 17.1 1442570397 9-59-57-18-9-2015

     

滋润100 17.6 1442574014 11-0-14-18-9-2015

     

滋润100 17.6 1442574030 11-0-30-18-9-2015

此处输出跳至0-0-0-19-9-2015(是的,我在日志中缺少一小时的条目)

$ sudo statanhourtest.sh

100,1.4,1.40,-98.6      16.5,17.2,16.90,.7      1442566811      9-0-0-18-9-2015

removing: 9th hour of the 18th day  of the 9th month
$ sudo statanhourtest.sh

100,1.4,1.40,-98.6      18.3,18.8,18.57,.5      1442620804      0-0-0-19-9-2015

removing: 0th hour of the 19th day  of the 9th month

问题只发生在几个小时。 ($dom)天匹配正常。

我尝试过使用grep的 -w 选项,但我认为这只会返回我需要整行的完全匹配。

在grep中字面上匹配数字并不多。我没有发现使用bash变量作为数字文字。

非常感谢任何帮助或相关链接。

修改: 经过一夜疏浚脚本后,我解决了这个问题。 问题出在我的 sed 表达式的最后。 问题在于单引号部分sed表达式和双引用变量以供shell扩展。 我从另一个线程的建议中得到了这个。 双引用整个表达式解决了这个问题。

awk 建议极大地提高了脚本的效率和准确性。再次感谢。

1 个答案:

答案 0 :(得分:0)

要求救援!

我认为您可以将所有内容组合到一个简单的awk脚本中,而无需任何正则表达式。例如,

awk 'NR==1{split($NF,h,"-")} {split($NF,t,"-")} t[1]==h[1] && t[4]==h[4]'

将解析文件第一行的时间戳,并仅过滤小时和天匹配记录。

这将采用字段2的平均值

awk 'NR==1
     {
          split($NF,h,"-")
     } 
     {             
          split($NF,t,"-")
     } 
     t[1]==h[1] && t[4]==h[4]
     {
          sum+=$2;
          c++
     } 
     END 
     {
          print "Average: " sum/c
     }'