在模式之间一起awk打印特定的变量和原始数据

时间:2018-09-25 12:38:27

标签: design-patterns awk pattern-matching

original data and desired output

你好

我想在模式之间获取特定的变量值并在其前面打印( REF_ID 值, C_ID 值和日期时间)。 / p>

您可以在下面看到原始数据和所需的输出:

输入:

[2018 13:50] ALI
REF_ID X 
A 3 
C_ID Y 
B 4 
[2018 14:00] ALI
C 3 
REF_ID Z 
D 1 
E 4 
C_ID T 

所需的输出:

[2018 13:50] X Y [2018 13:50] ALI
[2018 13:50] X Y REF_ID X 
[2018 13:50] X Y A 3 
[2018 13:50] X Y C_ID Y 
[2018 13:50] X Y B 4 
[2018 14:00] Z T [2018 14:00] ALI
[2018 14:00] Z T C 3 
[2018 14:00] Z T REF_ID Z 
[2018 14:00] Z T D 1 
[2018 14:00] Z T E 4 
[2018 14:00] Z T C_ID T 

我尝试了以下操作,但无法按我的要求工作。

awk '
BEGIN {FS=" "}
{if ($0 ~ /\[2018/) {flag=1;date_ref=$1;time_ref=$2;}            }
{if ($0 ~ /REF_ID/ ) {t_ref=$2}                   }
{if ($0 ~ /C_ID/ ) {gcid_ref=$2}        }
{if (flag=1) print date_ref,time_ref,t_ref,gcid_ref,$0}
'

我得到的输出:

[2018 13:50]   [2018 13:50] ALI
[2018 13:50] X  REF_ID X 
[2018 13:50] X  A 3 
[2018 13:50] X Y C_ID Y 
[2018 13:50] X Y B 4 
[2018 14:00] X Y [2018 14:00] ALI
[2018 14:00] X Y C 3 
[2018 14:00] Z Y REF_ID Z 
[2018 14:00] Z Y D 1 
[2018 14:00] Z Y E 4 
[2018 14:00] Z T C_ID T 

要解决这个问题,我相信必须将数据放入缓冲区,收集变量并将其合并。

能帮我解决这个问题吗?如果您可以解释所提供的代码,将会很有帮助。

2 个答案:

答案 0 :(得分:1)

我相信您可能对此感兴趣:

awk '($1 ~ /^\[/) && record { 
        string= date_ref OFS time_ref OFS t_ref OFS gcid_ref OFS
        gsub(ORS,ORS string, record)
        print string record 
        record=""
     }
    ($1 ~ /^\[/) { date_ref=$1; time_ref=$2 }
    ($1 == "REF_ID") { t_ref=$2 }
    ($1 == "C_ID")   { gcid_ref=$2 }
    { record = record ? record ORS $0 : $0 }
    END { string= date_ref OFS time_ref OFS t_ref OFS gcid_ref OFS
          gsub(ORS,ORS string, record)
          print string record 
    }' <file>

输出:

[2018 13:50] X Y [2018 13:50] ALI
[2018 13:50] X Y REF_ID X 
[2018 13:50] X Y A 3 
[2018 13:50] X Y C_ID Y 
[2018 13:50] X Y B 4 
[2018 14:00] Z T [2018 14:00] ALI
[2018 14:00] Z T C 3 
[2018 14:00] Z T REF_ID Z 
[2018 14:00] Z T D 1 
[2018 14:00] Z T E 4 
[2018 14:00] Z T C_ID T

以上代码的想法是在打印任何内容之前将record内置到内存中。在建立记录时,您会选择相关信息,例如date_ref time_reft_refgcid_ref

  1. ($1 ~ /^\[/) && record记录开始时(以[开头的行表示),您必须根据选择的信息对上一条记录执行操作。 (除非它为空)

    1. string= date_ref OFS time_ref OFS t_ref OFS gcid_ref OFS:构建要放置在每行之前的stringOFS默认为空格)
    2. gsub(ORS,ORS string, record)ORS替换所有换行符(默认值ORS string
    3. print string record ::打印记录,记录前面有字符串 作为第一行,它前面没有字符串。
    4. record=""重设record,因为从现在开始建立新记录。
  2. ($1 ~ /^\[/) { ... }($1 == "REF_ID"){...}($1 == "C_ID") { }:在满足正确条件(即第一个字段等于或匹配适当的事物)时提取相关信息。

  3. { record = record ? record ORS $0 : $0 }通过在当前行后面添加换行符来构建记录(ORS默认为换行符)。请注意,您必须检查记录是否为空,以便开头没有多余的ORS

  4. END,您仍然需要打印最后一条记录。再次执行步骤1中的所有操作。

答案 1 :(得分:1)

$ cat tst.awk
/^\[/ {
    prt()
    time = $1 FS $2
}
{
    map[$1] = $2     # save every 1st field to 2nd field mapping,
                     # e.g. map["REF_ID"]="X", map["C_ID"]="Y", etc.
    rec[++numLines] = $0
}
END { prt() }
function prt(   lineNr) {
    for (lineNr=1; lineNr<=numLines; lineNr++) {
        # now just retrieve the 2nd field values by their 1st field names
        print time, map["REF_ID"], map["C_ID"], rec[lineNr]
    }
    numLines = 0
}

$ awk -f tst.awk file
[2018 13:50] X Y [2018 13:50] ALI
[2018 13:50] X Y REF_ID X
[2018 13:50] X Y A 3
[2018 13:50] X Y C_ID Y
[2018 13:50] X Y B 4
[2018 14:00] Z T [2018 14:00] ALI
[2018 14:00] Z T C 3
[2018 14:00] Z T REF_ID Z
[2018 14:00] Z T D 1
[2018 14:00] Z T E 4
[2018 14:00] Z T C_ID T