UNIX (AIX) script to process a file using only awk or other file processing utilities

I have a task to write a script that will filter the input from the MQ runmqsc command and redirect the output to another file. I work on many other Linux commands connected together, and it seems to work fine on Linux, but my manager needs to run the script on the AIX system, therefore on the UNIX operating system. I learned that many commands that work fine on Linux or run on Linux will produce completely different output on UNIX or UNIX systems. The result of the runmqsc command is as follows:

5724-H72 (C) Copyright IBM Corp. 1994, 2009. ALL RIGHTS RESERVED. Starting MQSC for queue manager CNUMQ02B. 1 : DISPLAY QLOCAL(*) CURDEPTH AMQ8409: Display Queue details. QUEUE(ADEXA.AOM.REPLY.MR.QL) TYPE(QLOCAL) CURDEPTH(0) AMQ8409: Display Queue details. QUEUE(ADEXA.AOM.REPLY.QL) TYPE(QLOCAL) CURDEPTH(0) AMQ8409: Display Queue details. QUEUE(ADEXA.ERROR.QL) TYPE(QLOCAL) CURDEPTH(0) AMQ8409: Display Queue details. QUEUE(ADEXA.FACT.OUT.QL) TYPE(QLOCAL) CURDEPTH(0) AMQ8409: Display Queue details. QUEUE(ADW.REMAN.XREF.ERR.QL) TYPE(QLOCAL) CURDEPTH(14) AMQ8409: Display Queue details. QUEUE(SAPNA.MESS.CRITICAL.CLASS.RESUME.QL) TYPE(QLOCAL) CURDEPTH(123) One MQSC command read. No commands have a syntax error. All valid MQSC commands were processed. 

Basically I only need to display the queue name, space, and then the depth of the queue on the same line, without trailing spaces and newlines at the beginning or end of the file, so it will look like a csv file with a space as a separator. I also need to filter the queues with the queue depth equal to 0, so the result will look like this:

 ADW.REMAN.XREF.ERR.QL 14 

As I said, I tried many commands on Linux, but I don’t know which commands and flags work more or less the same on UNIX and Linux, and my manager wants it today, so if you accidentally read this, I ask you though would guide me what to use to try to figure it out :) Thanks.

This is what I wrote on Linux:

 head -n -3 "$1" | tail -n +6 | sed '/AMQ8409: Display Queue details./d' | sed 's/TYPE(QLOCAL)//g' | tr -d ' \t\r\f' | awk 'NR%2{printf "%s ",$0;next;}1' | sed '/CURDEPTH(0)/d' | awk '{gsub(/QUEUE(/, ""); gsub(/CURDEPTH(/, ""); gsub(/)/, ""); print}' | sort -nk2 
+5
source share
6 answers

Try this simpler command.

 sed -n -e 's/.*QUEUE(\([^)]*\)).*/\1/p' -e 's/.*CURDEPTH(\([0-9]*\)).*/\1/p' \ | paste -d ' ' - - \ | grep -v ' 0$' 
+2
source
 $ awk '/QUEUE|CURDEPTH\(/ { # on matching records gsub(/^[^(]+\(|).*$/,""); # remove unwanted parts printf "%s%s", $0, ($0~/^[0-9]+$/?ORS:OFS) # print ORS after depth }' file ADEXA.AOM.REPLY.MR.QL 0 ADEXA.AOM.REPLY.QL 0 ADEXA.ERROR.QL 0 ADEXA.FACT.OUT.QL 0 ADW.REMAN.XREF.ERR.QL 14 
+1
source

Here is one that does not use gsub :

 awk -F "[()]" '/QUEUE/ {quename=$2} /CURDEPTH\(/ {print quename, $2} ' 
+1
source

Instead of using "head" and "tail" and "sed" to remove unwanted lines, use grep to take the ones you want. I'm not sure which of these options will work on AIX, but they all have to believe me.

 grep -B 1 CURDEPTH $1 grep -A 1 QUEUE $1 grep -e QUEUE -e CURDEPTH $1 

Then concatenate and format the lines:

 sed 's#.*QUEUE(\([^)]*\)).*\n.*CURDEPTH(\([0-9]*\)).*#\1 \2#' 

If this does not work properly, try using '\ r' instead of '\ n'.

Finally, delete all lines with a depth of 0 (2 options):

 grep -v " 0$" sed '# 0$#d' 

I am not very familiar with this form of sed - I pinched it from your sample code, but it looks simple, so it should work.

All of these commands refer to the most basic form you can get, so they should work equally well on any * nix system. With hope. Initial grep and sed are the highest risk points.

+1
source

This works for me on AIX to get the desired result. This uses the IBM MQ WHERE to limit queued output with CURDEPTH greater than 0:

 echo "DIS QL(*) WHERE(CURDEPTH GT 0)" | runmqsc <qmgr> | sed -e 's/\((.*)\) *\(.*\)/\1\ \2/g' -e 's/^ *\([AZ][AZ]*[(][^)][^)]*[)]\)/\1/g' -e 's/^\(AMQ[0-9][0-9]*:\).*$/\1/g' | awk -F '[()]' -v OFS=" " 'function printValues() { if ("QUEUE" in p) { print p["QUEUE"], p["CURDEPTH"] } } /AMQ8409:/ { printValues(); for (i in p) { delete p[i] }; next } { p[$1] = $2 } END { printValues() }' 

Note that the above two lines, \ at the end of the first line allows the sed command to replace the inline new line. Syntax awk printValues ​​from @ mike.dld answer to this post Print part of the array or file and sort in the shell . "I had to replace its delete p with for (i in p) { delete p[i] } , since AIX awk did not support other syntax.

If you want to use the file as an input file, use the following:

 cat file | sed -e 's/\((.*)\) *\(.*\)/\1\ \2/g' -e 's/^ *\([AZ][AZ]*[(][^)][^)]*[)]\)/\1/g' -e 's/^\(AMQ[0-9][0-9]*:\).*$/\1/g' | awk -F '[()]' -v OFS=" " 'function printValues() { if ("QUEUE" in p) { print p["QUEUE"], p["CURDEPTH"] } } /AMQ8409:/ { printValues(); for (i in p) { delete p[i] }; next } { p[$1] = $2 } END { printValues() }' | grep -v ' 0$' 

Easily add any number of attributes to the output. If you want to expand it in the future, you simply add more entries to the awk command for each attribute required as follows:, , p["ATTR1"], p["ATTR2"]

Using MAXDEPTH as an example:

 echo "DIS QL(*) WHERE(CURDEPTH GT 0)" | runmqsc <qmgr> | sed -e 's/\((.*)\) *\(.*\)/\1\ \2/g' -e 's/^ *\([AZ][AZ]*[(][^)][^)]*[)]\)/\1/g' -e 's/^\(AMQ[0-9][0-9]*:\).*$/\1/g' | awk -F '[()]' -v OFS=" " 'function printValues() { if ("QUEUE" in p) { print p["QUEUE"], p["CURDEPTH"], p["MAXDEPTH"] } } /AMQ8409:/ { printValues(); for (i in p) { delete p[i] }; next } { p[$1] = $2 } END { printValues() }' 

Please note that this answer and possibly others will have a problem if the attribute itself has a built-in bracket, this is possible in the DESCR field of the queue and is true for various other fields for other types of objects. One common example is the CONNAME attribute for CHANNEL . CONNAME uses the hostname(port) format, therefore it is displayed as CONNAME(hostname(port)) .

+1
source

With awk this can be done relatively easily:

 runmqsc "display qlocal(*) curdepth" | awk ' /QUEUE\(/ { gsub(/^[^\(]*\(/, "", $0); gsub(/\).*$/, "", $0); qname = $0; } /CURDEPTH\(/ { gsub(/^[^\(]*\(/, "", $0); gsub(/\).*$/, "", $0); print qname" "$0; }' 

Basically, it just extracts the queue name from the lines containing QUEUE( , and saves them later.

When it finds lines containing CURDEPTH( , it extracts the depth in the same way, and then displays it along with the saved queue name.

The two gsub calls in each section look like black magic, but they are easy to understand when you know what they mean. The first finds the pattern at the beginning of the line, consisting of the largest number of non ( characters, followed by the character ( , and then does not replace anything.

The second is similar, but removes the largest sequence " ) , followed by any characters to the end of the line."

0
source

Source: https://habr.com/ru/post/1263186/


All Articles