簡體   English   中英

使用AWK從多行提取信息

[英]Extract Information from multiple lines using 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

您可以使用以下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

使用awk多維數組:

awk '/EKYC/ { cnt++;cnt1=0 } $0 != "EKYC" { cnt1++;if ($2 ~ "not") { $2 = "null" } dat[cnt,cnt1]=$2 } END { for (i=1;i<=cnt;i++) { for (p=1;p<=cnt1;p++) { printf "%s\t",dat[i,p] } print "" } }' filename

看到EKYC時,設置增量cnt,然后重新初始化cnt1。 使用計數器創建和存儲第二個空間已分配數據的數據數組。 最后遍歷多維數組以打印數據。

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

每當您擁有數據中的“名稱/值”對時,最好的方法是首先創建一個捕獲該映射的數組(下面的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" ,然后再次不需要該修改。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM