Print part of an array or a file and sort in shell

2020-05-09 04:54发布

I have a text file as follows

     1 : dis conn(*) type(CONN) all where(UOWLOG ne '')
AMQ8276: Display Connection details.
   CONN(AE1CA9572C47D822)                
   EXTCONN(414D51434D5147575032202020202020)
   TYPE(CONN)                            
   PID(9098)                               TID(503215) 
   APPLDESC(WebSphere MQ Channel)       
   APPLTAG(WebSphere MQ Client for Java)
   APPLTYPE(USER)                          ASTATE(NONE)
   CHANNEL(ABIS.CLIENT)           CLIENTID( )
   CONNAME(101.54.151.80)               
   CONNOPTS(MQCNO_HANDLE_SHARE_BLOCK,MQCNO_FASTPATH_BINDING)
   USERID(malth)                         UOWLOG(S0599315.LOG)
   UOWSTDA(2016-08-16)                     UOWSTTI(11.06.38)
   UOWLOGDA(2016-08-16)                    UOWLOGTI(11.06.38)
   URTYPE(QMGR)                         
   EXTURID(XA_FORMATID[] XA_GTRID[] XA_BQUAL[])
   QMURID(0.190537069)                     UOWSTATE(ACTIVE)
AMQ8276: Display Connection details.
   CONN(AE1CA957D787F429)                
   EXTCONN(414D51434D5147575032202020202020)
   TYPE(CONN)                            
   PID(28292)                              TID(1519092) 
   APPLDESC(WebSphere MQ Channel)       
   APPLTAG(WebSphere MQ Client for Java)
   APPLTYPE(USER)                          ASTATE(NONE)
   CHANNEL(SB.CLIENT)                  CLIENTID( )
   CONNAME(101.54.151.119)              
   CONNOPTS(MQCNO_HANDLE_SHARE_BLOCK,MQCNO_FASTPATH_BINDING)
   USERID(sbp)                         UOWLOG(S0599317.LOG)
   UOWSTDA(2016-08-16)                     UOWSTTI(11.07.38)
   UOWLOGDA(2016-08-16)                    UOWLOGTI(11.07.38)
   URTYPE(QMGR)                         
   EXTURID(XA_FORMATID[] XA_GTRID[] XA_BQUAL[])
   QMURID(0.190520281)                     UOWSTATE(ACTIVE)
AMQ8276: Display Connection details.
   CONN(2CC7AE57CE8E6221)                
   EXTCONN(414D51434D5147575032202020202020)
   TYPE(CONN)                            
   PID(22400)                              TID(647335) 
   APPLDESC(WebSphere MQ Channel)       
   APPLTAG(WebSphere MQ Client for Java)
   APPLTYPE(USER)                          ASTATE(NONE)
   CHANNEL(U90785.CBM.CLIENT)              CLIENTID( )
   CONNAME(101.54.163.37)               
   CONNOPTS(MQCNO_HANDLE_SHARE_BLOCK,MQCNO_FASTPATH_BINDING)
   USERID(machlth)                         UOWLOG(S0599317.LOG)
   UOWSTDA(2016-08-16)                     UOWSTTI(11.07.40)
   UOWLOGDA(2016-08-16)                    UOWLOGTI(11.07.40)
   URTYPE(QMGR)                         
   EXTURID(XA_FORMATID[] XA_GTRID[] XA_BQUAL[])
   QMURID(0.190574800)                     UOWSTATE(ACTIVE)
AMQ8276: Display Connection details.
   CONN(2CC7AE571BF0B721)                
   EXTCONN(414D51434D5147575032202020202020)
   TYPE(CONN)                            
   PID(22210)                              TID(1069968) 
   APPLDESC(WebSphere MQ Channel)       
   APPLTAG(WebSphere MQ Client for Java)
   APPLTYPE(USER)                          ASTATE(NONE)
   CHANNEL(APP.CLIENT)                  CLIENTID( )
   CONNAME(101.54.163.127)              
   CONNOPTS(MQCNO_HANDLE_SHARE_BLOCK,MQCNO_FASTPATH_BINDING)
   USERID(apsp)                            UOWLOG(S0599317.LOG)
   UOWSTDA(2016-08-16)                     UOWSTTI(11.07.29)
   UOWLOGDA(2016-08-16)                    UOWLOGTI(11.07.29)
   URTYPE(QMGR)                         
   EXTURID(XA_FORMATID[] XA_GTRID[] XA_BQUAL[])

Now i want my output to to show

ABIS.CLIENT,101.54.151.80,malth,S0599315.LOG,11.06.38
APP.CLIENT,101.54.163.127,apsp,S0599317.LOG,11.07.29
SB.CLIENT,101.54.151.119,sbp,S0599317.LOG,11.07.38
CBM.CLIENT,101.54.163.37,machlth,S0599317.LOG,11.07.40

so basically, get the channel name, conname, userid,UUOWLOG and UOWLOGTI and sort it all in the end by UOWLOGTI. I am trying to do this in shell.

I have tried using awk but can't seem to get the desired output.

cat UOWLOG.txt|awk -vRS="" 'BEGIN{printf ""}/\<'AMQ8276'\>/^CHANNEL{printf $0 RT}' I get errors when i try different options in awk. Please help.

标签: bash shell awk
4条回答
啃猪蹄的小仙女
2楼-- · 2020-05-09 05:05

all can be done in awk but perhaps easier with a chain of tools

$ grep -oP '(CHANNEL|CONNAME|USERID|UOWLOG|UOWLOGTI)\(.*?\)' file | 
  awk -F'[()]' '{ORS=NR%5?",":RS; print $2}' | 
  sort -t, -k5

ABIS.CLIENT,101.54.151.80,malth,S0599315.LOG,11.06.38
APP.CLIENT,101.54.163.127,apsp,S0599317.LOG,11.07.29
SB.CLIENT,101.54.151.119,sbp,S0599317.LOG,11.07.38
U90785.CBM.CLIENT,101.54.163.37,machlth,S0599317.LOG,11.07.40
查看更多
一纸荒年 Trace。
3楼-- · 2020-05-09 05:07

My lil bit dirty gnu awk solution:

$ awk -v RS="AMQ" 'NR>1{
print gensub(/.*CHANNEL\(([^)]+).*CONNAME\(([^)]+).*USERID\(([^)]+).*UOWLOG\(([^)]+).*UOWLOGTI\(([^)]+).*/,"\\1,\\2,\\3,\\4,\\5","1")}' file | sort -t "," -k5
ABIS.CLIENT,101.54.151.80,malth,S0599315.LOG,11.06.38
APP.CLIENT,101.54.163.127,apsp,S0599317.LOG,11.07.29
SB.CLIENT,101.54.151.119,sbp,S0599317.LOG,11.07.38
U90785.CBM.CLIENT,101.54.163.37,machlth,S0599317.LOG,11.07.40
查看更多
够拽才男人
4楼-- · 2020-05-09 05:07

I dunno, but the accepted answer doesn't produce the specified output for the "CBM.CLIENT" channel, and all the answers so far are intense one-liners. When the transformation is this complex, I like whole script, so I can see what's what.

#! /usr/bin/awk -f 

function Print() {
    OFS = ","
    print line["CHANNEL"], line["CONNAME"], line["USERID"],     \
          line["UOWLOG"], line["UOWLOGTI"]
    delete line
}

/Display Connection details[.]$/ {
    if( length(line) ) {
        Print()
    }
    next
}

$1 == "CHANNEL" {
    line[$1] = $2
    if( 3 == split( $2, channel, /[.]/ ) ) {
        line[$1] = channel[2] "." channel[3]
    }
    next
}

{
    line[$1] = $2
}

END { Print() }

The technique is to build an associative array of all the foo(bar) elements, and print the interesting bits in an obvious way. The regexes are simple and input assumptions are relaxed: no field-order dependency, and very little formatting dependency.

It relies on a little pre-processing to put each key/value pair on its own line, and post-processing to sort the output. Invoke as:

$ cat f.sh
#! /bin/sh
sed -E 's/^ +//; s/ +$//g; s/  +/\
/g'  $1 | awk -F '[:()]' -f script.awk | sort -t, -k5

$ ./f.sh dat
ABIS.CLIENT,101.54.151.80,malth,S0599315.LOG,11.06.38
APP.CLIENT,101.54.163.127,apsp,S0599317.LOG,11.07.29
SB.CLIENT,101.54.151.119,sbp,S0599317.LOG,11.07.38
CBM.CLIENT,101.54.163.37,machlth,S0599317.LOG,11.07.40

In the comments, the OP mentions printing only lines that meet a certain criterion. That's easy to add to this Print() function, and easy to understand later, too.

查看更多
Ridiculous、
5楼-- · 2020-05-09 05:20

My solution is similar to @karakfa's but makes no assumptions for fields order:

$ grep -o '^\w\+:\|\w\+[(][^)]\+[)]' file |
  awk -F '[()]' -v OFS="," 'function printValues() { if ("CHANNEL" in p) { print p["CHANNEL"], p["CONNAME"], p["USERID"], p["UOWLOG"], p["UOWLOGTI"] } } /^\w+:/ { printValues(); delete p; next } { p[$1] = $2 } END { printValues() }' |
  sort -t, -k 5

What I'm doing is creating an associative array for each "record" and then only printing the fields necessary.

查看更多
登录 后发表回答