需要了解这个awk语句

时间:2013-01-16 06:25:36

标签: linux awk

我正在读这个问题 Awk code to select multiple patterns

用户将此作为输入

------------------------------------------------------------------------
r4544 | n479826 | 2012-08-28 07:12:33 -0400 (Tue, 28 Aug 2012) | 1 line
Changed paths:
   M /branches/8.6.0/conf/src/main/config/RTSConfig.xml

CET-402: some text comment
------------------------------------------------------------------------
r4550 | n479826 | 2012-09-04 05:51:29 -0400 (Tue, 04 Sep 2012) | 1 line
Changed paths:
   M /branches/8.6.0/conf/src/main/config/RTSConfig.xml
   M /branches/8.6.0/conf/src/main/config/base.cfg
   M /branches/8.6.0/conf/src/main/config/prod.cfg
   M /branches/8.6.0/conf/src/main/config/qa.cfg
   M /branches/8.6.0/conf/src/main/config/uat.cfg

CET-438: some text comment

他想把它作为输出

r4544 | n479826 | 2012-08-28 07:12:33 | /branches/8.6.0/conf/src/main/config/RTSConfig.xml
r4550 | n479826 | 2012-09-04 05:51:29 | /branches/8.6.0/conf/src/main/config/RTSConfig.xml
r4550 | n479826 | 2012-09-04 05:51:29 | /branches/8.6.0/conf/src/main/config/base.cfg
r4550 | n479826 | 2012-09-04 05:51:29 | /branches/8.6.0/conf/src/main/config/prod.cfg
r4550 | n479826 | 2012-09-04 05:51:29 | /branches/8.6.0/conf/src/main/config/qa.cfg
r4550 | n479826 | 2012-09-04 05:51:29 | /branches/8.6.0/conf/src/main/config/uat.cfg

正确答案是这个

awk -F"|" '/^r/{a=$1;b=$2;c=substr($3,0,20)}/^   M/{gsub(/   M /," ");print a"|"b"|"c"|"$0}' your_file

我完全不理解。

现在我得到了这个部分

/^r/{a=$1;b=$2;c=substr($3,0,20)}/^

但我没有得到第二部分 M/{gsub(/ M /," ");print a"|"b"|"c"|"$0}

我的问题是

  1. M在一开始就意味着什么 2.现在awk将逐行读取文件,因此它意味着在第二行 即Chngaed路径为a =0的值,因为该行上没有字段分隔符|
  2. 现在当awk到达第三行时 然后再次a,b,c =0$0 = /bracnhes但结果如何仍然显示a,b,c的旧值
  3. 当在多行上使用awk时,我感到困惑

3 个答案:

答案 0 :(得分:1)

这样做

/^r/{a=$1;b=$2;c=substr($3,0,20)}

  1. 它匹配以r开头的唯一行和一些数字。所以它得到a,b,c变量
  2. /^ M/{gsub(/ M /," ");print a"|"b"|"c"|"$0}

    1. 这与spaces and M的行标准相匹配,以获得另一部分。在此匹配过程中,a,b,c将从之前保存的值
    2. 中移除

答案 1 :(得分:1)

我懒得解释答案:) 但是lemme把我的懒惰搁置一段时间了:

/^r/{a=$1;b=$2;c=substr($3,0,20)}

只有当行以字母r开头时,才会执行上面的代码块。 在块内部表示将第一个字段存储在a中,第二个字段存储在b中,第三个字段存储在输入中:

2012-08-28 07:12:33 -0400 (Tue, 28 Aug 2012)

但我只需要带有时间戳的日期,其余的对我来说已经过时了。 它总是20个字符。 所以我从第三个字段中取出一个子字符串并将其存储在c。

我的主要兴趣是以/ ^ M /开头的行,我必须显示上一行中以r开头的信息 并且确定在我们想要的行之前有一行以r开头,其中包含所有信息,我必须在前面加上以M开头的行。

因此,每当一行以M开头时,将使用存储在b和c中的值作为前缀。

M/{gsub(/ M /," ");print a"|"b"|"c"|"$0}

gsub部分将从当前行中删除带有空格的“M”部分。 print部分只是将a和b的值预先设置为当前行的|作为分隔符。

这就是逻辑!

我现在将回到懒惰模式:)

答案 2 :(得分:0)

原因是在遇到M之前不会替换a,b和c的值。所以它仍附加在print语句中。