【问题标题】:how to write bash script to filter some data in logs如何编写bash脚本来过滤日志中的一些数据
【发布时间】:2015-10-19 18:47:15
【问题描述】:

我有一个这种格式的日志文件。

-----------------------------------------------------------
name=abc
address=country:US,Zip:12345/1,city:ny/1,state:ny/1, yearsLived:5/1,other details
healthDetails=healthplan:medixx/1, expensesInDollars:150/1, other details
-----------------------------------------------------------

name=xyz
address=country:US,Zip:12345/1,city:ny/1,state:ny/1, yearsLived:3/1,other details
healthDetails=healthplan:medixx/1, expensesInDollars:150/1, other details
-----------------------------------------------------------

name=awd
address=country:US,Zip:12345/1,city:ny/1,state:ny/1, yearsLived:2/1,other details
healthDetails=healthplan:medixx/1, expensesInDollars:150/1, other details
-----------------------------------------------------------

如果日志文件中每个名称的寿命大于特定年份(例如 2),我想提取此人的姓名和寿命。该文件也会有重复的名称,但细节不同。

输出:

name:abc
yearLived:5
name:xyz
yearsLived: 3

我试图使用 grep 和 cut 命令来做到这一点。我面临的问题是,一旦我执行 grep 或 cut 我会丢失另一部分,即名称或地址。我该如何解决这个问题?

【问题讨论】:

  • 不要使用grepcut。使用awk 或类似工具。
  • 每个值后面的 /1 是什么?并且总是以这种格式记录,即名称行后换行?
  • 这只是一些与日志相关的版本号(忽略它)。是的,格式总是一样的
  • @jas 更新了问题。尽管除了姓名和年份之外,我的信息几乎相同
  • awk 有帮助,因为您可以做的不仅仅是盲目地匹配和剪切文本。你有任意复杂的逻辑和更奇特的方法来将数据分解成记录。

标签: bash shell awk grep cut


【解决方案1】:

这是一个尝试:

awk 'BEGIN {RS = "name="} NR > 1 {match($0, "yearsLived:[0-9]+", yl) ; split(yl[0], years, ":")} NR > 1 && years[2] > 2 {print $1 "\t" years[2]}' records_file

编辑:容纳更新的日志行示例和所需的输出:

awk 'BEGIN {RS = "-{59}"} NR > 1 {match($0, "yearsLived:[0-9]+", yl) ; split(yl[0], years, ":")} NR > 1 && years[2] > 2 {sub("=", ":", $1); print $1 "\n" yl[0]}' records

编辑 2:糟糕,要添加注释:要更改匹配年数的阈值,请更改 years[2] > 2 中的第二个 2。希望对您有所帮助。

【讨论】:

  • 您能解释一下为什么在这里使用-59。我删除了它并尝试了您的第一条评论并且它有效。
  • 我正在设置记录分隔符。 awk 通常使用换行符来表示新记录,但您的文件似乎使用一系列 59 个连字符来分隔它们;因此,-{59}。在第一个中,我不确定(直到您提供更多数据可以使用)连字符是否真的在数据中,或者只是为了方便 SO。所以,我使用name= 作为分隔符。一旦清楚连字符确实在数据中,使用它就变得更容易了。
【解决方案2】:

像使用 awk 一样

awk '$0~/^name/{split($0,a,"=")}{if($0~/yearsLived:[3-9]/){split($0,b,":|/");print "name:",a[2] "\nyearsLived: "b[9]}}' 'my_file'

分解一行shell代码

创建一个名为awkscript 的文本文件并添加以下代码

#!/bin/awk
$0~/^name/{
    #find all lines that has name and reference in using an array 'a'   
    split($0,a,"=") 
          }
#find all lines that has years lived >2 and print name and years lived
{if($0~/yearsLived:[3-9]/){ 
    split($0,b,":|/");print "name:",a[2] "\nyearsLived: "b[9] #print name and year
}
}

现在在你的 shell 中运行 awk 脚本

 awk -f 'awkscript'  'my_file'

【讨论】:

  • 感谢 Xorg。最初,我首先将所有年份都保存在一个文件中,然后在原始日志中对其进行 grepping 以获取名称和所有内容。这使它更容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多