仅使用 awk 或其他文件处理实用程序处理文件的 UNIX(AIX) 脚本
UNIX(AIX) script to process a file using only awk or other file processing utilities
我的任务是编写一个脚本来过滤来自 MQ 运行mqsc 命令的输入并将输出重定向到另一个文件。我一直在使用许多其他 Linux 命令通过管道传输在一起,它似乎在 Linux 中工作得很好,但我的经理需要 运行 AIX 系统上的脚本,因此 UNIX 操作系统。
我意识到许多 运行 在 Linux 上运行良好或在 Linux 上完成工作的命令在 UNIX 或基于 UNIX 的系统上会产生完全不同的输出。
运行mqsc 命令的输出如下所示:
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.
我基本上需要做的只是在同一行显示队列名称、一个空格,然后是队列深度,没有尾随空格,文件开头或结尾没有换行符,所以它将类似于一个以空格作为分隔符的 csv 文件。我还需要过滤掉队列深度等于 0 的队列,因此输出将如下所示:
ADW.REMAN.XREF.ERR.QL 14
正如我所说,我在 Linux 上尝试了很多命令,但我不了解哪些命令和标志在 UNIX 和 Linux 上实际上或多或少地工作,我的经理今天想要这个,所以如果你有机会读到这篇文章,我要求你至少指导我使用什么来尝试解决它:)谢谢。
这是我在Linux中写的:
head -n -3 "" |
tail -n +6 |
sed '/AMQ8409: Display Queue details./d' |
sed 's/TYPE(QLOCAL)//g' |
tr -d ' \t\r\f' |
awk 'NR%2{printf "%s ",[=12=];next;}1' |
sed '/CURDEPTH(0)/d' |
awk '{gsub(/QUEUE(/, ""); gsub(/CURDEPTH(/, ""); gsub(/)/, ""); print}' |
sort -nk2
试试这个更简单的命令..
sed -n -e 's/.*QUEUE(\([^)]*\)).*//p' -e 's/.*CURDEPTH(\([0-9]*\)).*//p' \
| paste -d ' ' - - \
| grep -v ' 0$'
使用 awk
,可以相对容易地完成:
runmqsc "display qlocal(*) curdepth" | awk '
/QUEUE\(/ {
gsub(/^[^\(]*\(/, "", [=10=]);
gsub(/\).*$/, "", [=10=]);
qname = [=10=];
}
/CURDEPTH\(/ {
gsub(/^[^\(]*\(/, "", [=10=]);
gsub(/\).*$/, "", [=10=]);
print qname" "[=10=];
}'
这基本上只是从包含 QUEUE(
的行中提取队列名称并将其存储以备后用。
当它找到包含 CURDEPTH(
的行时,它会以相同的方式提取深度,然后将其与存储的队列名称一起输出。
每个部分中的两个 gsub
调用看起来像 "black magic",但一旦您了解它们的含义,它们就很容易理解。第一个在行首找到一个模式,该模式由最大数量的非 (
字符和后跟 (
字符组成,然后将其替换为空。
第二个类似,但它删除了最大的序列“)
,后跟任何字符到行尾”。
$ awk '/QUEUE|CURDEPTH\(/ { # on matching records
gsub(/^[^(]+\(|).*$/,""); # remove unwanted parts
printf "%s%s", [=10=], ([=10=]~/^[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
这是一个不使用 gsub
:
awk -F "[()]" '/QUEUE/ {quename=} /CURDEPTH\(/ {print quename, } '
与其使用 "head"、"tail" 和 "sed" 删除不需要的行,不如使用 grep 删除您想要的行。我不确定这些选项中的哪一个适用于 AIX,但我应该相信它们。
grep -B 1 CURDEPTH
grep -A 1 QUEUE
grep -e QUEUE -e CURDEPTH
接下来,加入并格式化行:
sed 's#.*QUEUE(\([^)]*\)).*\n.*CURDEPTH(\([0-9]*\)).*# #'
如果不能正常工作,请尝试使用“\r”而不是“\n”。
最后,删除深度为 0 的所有行(2 个选项):
grep -v " 0$"
sed '# 0$#d'
我对这种形式的 sed 不是很熟悉 - 我从你的代码示例中提取了它 - 但它看起来很简单所以应该可以工作。
所有这些命令都是关于您可以获得的最基本形式的,因此在任何 *nix 系统上都应该同样有效。希望。最开始的grep和sed是风险最高点。
这对我在 AIX 上有效以获取您需要的输出,它使用 IBM MQ 的 WHERE
子句将输出限制为 CURDEPTH 大于 0 的队列:
echo "DIS QL(*) WHERE(CURDEPTH GT 0)" | runmqsc <qmgr> | sed -e 's/\((.*)\) *\(.*\)/\
/g' -e 's/^ *\([A-Z][A-Z]*[(][^)][^)]*[)]\)//g' -e 's/^\(AMQ[0-9][0-9]*:\).*$//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[] = } END { printValues() }'
注意上面是两行,第一行末尾的\允许sed命令替换为嵌入的新行。 awk printValues 语法来自@mike.dld 对此post“”的回答。我不得不用 for (i in p) { delete p[i] }
替换他的 delete p
因为 AIX awk 不支持其他语法。
如果您想 运行 使用文件作为输入,请使用以下命令:
cat file | sed -e 's/\((.*)\) *\(.*\)/\
/g' -e 's/^ *\([A-Z][A-Z]*[(][^)][^)]*[)]\)//g' -e 's/^\(AMQ[0-9][0-9]*:\).*$//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[] = } END { printValues() }' | grep -v ' 0$'
很容易向输出添加任意数量的属性。如果你想在未来扩展它,你只需为每个需要的属性向 awk 命令添加更多条目,如下所示:, p["ATTR1"], p["ATTR2"]
以MAXDEPTH
为例:
echo "DIS QL(*) WHERE(CURDEPTH GT 0)" | runmqsc <qmgr> | sed -e 's/\((.*)\) *\(.*\)/\
/g' -e 's/^ *\([A-Z][A-Z]*[(][^)][^)]*[)]\)//g' -e 's/^\(AMQ[0-9][0-9]*:\).*$//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[] = } END { printValues() }'
请注意,如果属性本身嵌入了括号,这个答案和其他答案可能会有问题,这在队列的 DESCR
字段中是可能的,并且是其他对象类型上的各种其他字段也是如此。一个常见的例子是 CHANNEL
的 CONNAME
属性。 CONNAME
使用格式 hostname(port)
因此显示为 CONNAME(hostname(port))
.
我的任务是编写一个脚本来过滤来自 MQ 运行mqsc 命令的输入并将输出重定向到另一个文件。我一直在使用许多其他 Linux 命令通过管道传输在一起,它似乎在 Linux 中工作得很好,但我的经理需要 运行 AIX 系统上的脚本,因此 UNIX 操作系统。 我意识到许多 运行 在 Linux 上运行良好或在 Linux 上完成工作的命令在 UNIX 或基于 UNIX 的系统上会产生完全不同的输出。 运行mqsc 命令的输出如下所示:
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.
我基本上需要做的只是在同一行显示队列名称、一个空格,然后是队列深度,没有尾随空格,文件开头或结尾没有换行符,所以它将类似于一个以空格作为分隔符的 csv 文件。我还需要过滤掉队列深度等于 0 的队列,因此输出将如下所示:
ADW.REMAN.XREF.ERR.QL 14
正如我所说,我在 Linux 上尝试了很多命令,但我不了解哪些命令和标志在 UNIX 和 Linux 上实际上或多或少地工作,我的经理今天想要这个,所以如果你有机会读到这篇文章,我要求你至少指导我使用什么来尝试解决它:)谢谢。
这是我在Linux中写的:
head -n -3 "" |
tail -n +6 |
sed '/AMQ8409: Display Queue details./d' |
sed 's/TYPE(QLOCAL)//g' |
tr -d ' \t\r\f' |
awk 'NR%2{printf "%s ",[=12=];next;}1' |
sed '/CURDEPTH(0)/d' |
awk '{gsub(/QUEUE(/, ""); gsub(/CURDEPTH(/, ""); gsub(/)/, ""); print}' |
sort -nk2
试试这个更简单的命令..
sed -n -e 's/.*QUEUE(\([^)]*\)).*//p' -e 's/.*CURDEPTH(\([0-9]*\)).*//p' \
| paste -d ' ' - - \
| grep -v ' 0$'
使用 awk
,可以相对容易地完成:
runmqsc "display qlocal(*) curdepth" | awk '
/QUEUE\(/ {
gsub(/^[^\(]*\(/, "", [=10=]);
gsub(/\).*$/, "", [=10=]);
qname = [=10=];
}
/CURDEPTH\(/ {
gsub(/^[^\(]*\(/, "", [=10=]);
gsub(/\).*$/, "", [=10=]);
print qname" "[=10=];
}'
这基本上只是从包含 QUEUE(
的行中提取队列名称并将其存储以备后用。
当它找到包含 CURDEPTH(
的行时,它会以相同的方式提取深度,然后将其与存储的队列名称一起输出。
每个部分中的两个 gsub
调用看起来像 "black magic",但一旦您了解它们的含义,它们就很容易理解。第一个在行首找到一个模式,该模式由最大数量的非 (
字符和后跟 (
字符组成,然后将其替换为空。
第二个类似,但它删除了最大的序列“)
,后跟任何字符到行尾”。
$ awk '/QUEUE|CURDEPTH\(/ { # on matching records
gsub(/^[^(]+\(|).*$/,""); # remove unwanted parts
printf "%s%s", [=10=], ([=10=]~/^[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
这是一个不使用 gsub
:
awk -F "[()]" '/QUEUE/ {quename=} /CURDEPTH\(/ {print quename, } '
与其使用 "head"、"tail" 和 "sed" 删除不需要的行,不如使用 grep 删除您想要的行。我不确定这些选项中的哪一个适用于 AIX,但我应该相信它们。
grep -B 1 CURDEPTH
grep -A 1 QUEUE
grep -e QUEUE -e CURDEPTH
接下来,加入并格式化行:
sed 's#.*QUEUE(\([^)]*\)).*\n.*CURDEPTH(\([0-9]*\)).*# #'
如果不能正常工作,请尝试使用“\r”而不是“\n”。
最后,删除深度为 0 的所有行(2 个选项):
grep -v " 0$"
sed '# 0$#d'
我对这种形式的 sed 不是很熟悉 - 我从你的代码示例中提取了它 - 但它看起来很简单所以应该可以工作。
所有这些命令都是关于您可以获得的最基本形式的,因此在任何 *nix 系统上都应该同样有效。希望。最开始的grep和sed是风险最高点。
这对我在 AIX 上有效以获取您需要的输出,它使用 IBM MQ 的 WHERE
子句将输出限制为 CURDEPTH 大于 0 的队列:
echo "DIS QL(*) WHERE(CURDEPTH GT 0)" | runmqsc <qmgr> | sed -e 's/\((.*)\) *\(.*\)/\
/g' -e 's/^ *\([A-Z][A-Z]*[(][^)][^)]*[)]\)//g' -e 's/^\(AMQ[0-9][0-9]*:\).*$//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[] = } END { printValues() }'
注意上面是两行,第一行末尾的\允许sed命令替换为嵌入的新行。 awk printValues 语法来自@mike.dld 对此post“for (i in p) { delete p[i] }
替换他的 delete p
因为 AIX awk 不支持其他语法。
如果您想 运行 使用文件作为输入,请使用以下命令:
cat file | sed -e 's/\((.*)\) *\(.*\)/\
/g' -e 's/^ *\([A-Z][A-Z]*[(][^)][^)]*[)]\)//g' -e 's/^\(AMQ[0-9][0-9]*:\).*$//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[] = } END { printValues() }' | grep -v ' 0$'
很容易向输出添加任意数量的属性。如果你想在未来扩展它,你只需为每个需要的属性向 awk 命令添加更多条目,如下所示:, p["ATTR1"], p["ATTR2"]
以MAXDEPTH
为例:
echo "DIS QL(*) WHERE(CURDEPTH GT 0)" | runmqsc <qmgr> | sed -e 's/\((.*)\) *\(.*\)/\
/g' -e 's/^ *\([A-Z][A-Z]*[(][^)][^)]*[)]\)//g' -e 's/^\(AMQ[0-9][0-9]*:\).*$//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[] = } END { printValues() }'
请注意,如果属性本身嵌入了括号,这个答案和其他答案可能会有问题,这在队列的 DESCR
字段中是可能的,并且是其他对象类型上的各种其他字段也是如此。一个常见的例子是 CHANNEL
的 CONNAME
属性。 CONNAME
使用格式 hostname(port)
因此显示为 CONNAME(hostname(port))
.