使用AWK从多行提取信息

时间:2017-09-08 08:23:20

标签: bash awk

我正在尝试使用awk从多行中提取不同的详细信息。 但是,我无法运行测试,并将结果输出打印在一行中。

信息位于不同的块中,然后我需要提取块内的详细信息..

awk '
     TRA TRB TRC
     /EKYC/{for(i=1; i<10; i++)
              {   (getline p )
                  if ( match(p,"TRA")) { print substr(p,4)}
                  if ( match(p,"TRB")) { print substr(p,4)}
                  if ( match(p,"TRC")) { print substr(p,4)}
              }
           }
    ' inputfile

EKYC块将在那里,代码TRA TRB TRC将位于EKYC块之间。

示例文本文件如下所示::

EKYC
TRA    onlyThisTRA1
TRB    onlyThisTRB1
THR    notThis
EKYC
TRA    onlyThisTRA2
TRB    onlyThisTRB2
TRC    onlyThisTRC2
EKYC
NOT
TRA    onlyThisTRA3
YEH    not this
TRC    onlyThisTRC3

所需的输出..每块一行

onlyThisTRA1 onlyThisTRA2 null
onlyThisTRA2 onlyThisTRB2 onlyThisTRC2
onlyThisTRA3 null         onlyThisTRC3

4 个答案:

答案 0 :(得分:1)

您可以使用此awk命令:

awk '/EKYC/{if (tra != "null") print tra, trb, trc; tra=trb=trc="null"; next}
$1=="TRA"{tra=$2} $1=="TRB"{trb=$2} $1=="TRC"{trc=$2}
END{print tra, trb, trc}' file

onlyThisTRA1 onlyThisTRB1 null
onlyThisTRA2 onlyThisTRB2 onlyThisTRC2
onlyThisTRA3 null onlyThisTRC3

答案 1 :(得分:1)

使用awk多维数组:

n

当看到EKYC时设置增量cnt并重新初始化cnt1。使用计数器创建存储第二个空间数据的数据和数组。最后循环遍历多维数组以打印数据。

答案 2 :(得分:1)

awk 解决方案:

awk 'function pr(a){ 
         n="null"; tra=a["TRA"]; trb=a["TRB"]; trc=a["TRC"]; 
         printf "%s %s %s\n",(tra)? tra:n,(trb)? trb:n,(trc)? trc:n; delete a 
     }
     /EKYC/{ if(f){ pr(a); f=0 } }
     /^TR[ABC]/{ a[$1]=$2; f=1 }END{ pr(a) }' file

输出:

onlyThisTRA1 onlyThisTRB1 null
onlyThisTRA2 onlyThisTRB2 onlyThisTRC2
onlyThisTRA3 null onlyThisTRC3

答案 3 :(得分:1)

每当您拥有数据中的名称 - 值对时,最好的方法是首先创建一个捕获该映射的数组(下面为n2v[]),然后您可以按名称引用这些值:

$ cat tst.awk
BEGIN  { OFS="\t" }
/EKYC/ { prt(); next }
       { n2v[$1] = $2 }
END    { prt() }
function prt() { if (length(n2v)) print v("TRA"), v("TRB"), v("TRC"); delete n2v }
function v(n)  { return (n in n2v ? n2v[n] : "null") }

$ awk -f tst.awk file
onlyThisTRA1    onlyThisTRB1    null
onlyThisTRA2    onlyThisTRB2    onlyThisTRC2
onlyThisTRA3    null    onlyThisTRC3

请注意,上面提到的每个名称在大写或小写中都只显示一次,并且没有基于数据中的值命名的变量,因此如果您需要添加新名称,则需要得到打印(例如“THC”)然后你只需在prt()函数中添加, v("THC"),它只在一个地方指定默认的null值,所以如果你想要一个不同的默认值或不同的算法要确定默认值,您只需更改v()函数。

修改脚本以接受要在命令行上打印的名称列表实际上是微不足道的:

$ cat tst.awk
BEGIN  { OFS="\t" }
/EKYC/ { prt(); next }
       { val=$0; sub(/^[^[:space:]]+[[:space:]]+/,"",val); n2v[$1] = val }
END    { prt() }
function prt(       nameList,nameNr,numNames) {
    if (length(n2v)) {
        numNames = split(names,nameList)
        for (nameNr=1; nameNr <= numNames; nameNr++) {
            printf "%s%s", v(nameList[nameNr]), (nameNr<numNames ? OFS : ORS)
        }
        delete n2v
    }
}
function v(n)  { return (n in n2v ? n2v[n] : "null") }

$ awk -v names='TRA TRB TRC' -f tst.awk file
onlyThisTRA1    onlyThisTRB1    null
onlyThisTRA2    onlyThisTRB2    onlyThisTRC2
onlyThisTRA3    null    onlyThisTRC3

$ awk -v names='TRA THR TRC YEH' -f tst.awk file
onlyThisTRA1    notThis null    null
onlyThisTRA2    null    onlyThisTRC2    null
onlyThisTRA3    null    onlyThisTRC3    not this

请注意,我修改了在第二个脚本中填充n2v[]的方式,以允许在您的名称值之后出现空格,因为您的YEH值(我现在在上面打印)有一个空间。如果没有空格,则不需要进行更改,如果分隔符是制表符,则只需在BEGIN部分设置FS="\t",然后再不需要修改。