使用AWK并将结果设置为bash变量/数组?

时间:2015-02-08 06:40:18

标签: linux bash awk

我有一个文件可以复制mySQL的show processlist命令的结果。 该文件如下所示:

*************************** 1. row ***************************
Id: 1
User: system user
Host:
db: NULL
Command: Connect
Time: 1030455
State: Waiting for master to send event
Info: NULL
*************************** 2. row ***************************
Id: 2
User: system user
Host:
db: NULL
Command: Connect
Time: 1004
State: Has read all relay log; waiting for the slave
       I/O thread to update it
Info: NULL

它在同一个结构中继续进行了几次。

我想使用AWK只获取这些参数:时间,ID,命令和状态,并将这些参数中的每一个存储到不同的变量或数组中,以便稍后在我的bash shell中使用/打印它们。 / p>

问题是,我对AWK很不好,我不知道如何从文件中分离出我想要的参数,并将它们设置为bash变量或数组。

非常感谢您的帮助!

编辑:到目前为止我的代码是

echo "Enter age"
read age
cat data | awk 'BEGIN{ RS="row"
FS="\n"
OFS="\n"}
{ print $2,$7}
' | awk 'BEGIN{ RS="Id"}
{if ($4 > $age){print $2}}'

文件'数据'包含我上面粘贴的块。代码应该,如果' age'输入小于数据文件中的Time参数(我的awk代码为$ 4),返回ID参数,但不返回任何内容。

如果我删除if语句并打印$ 4而不是$ 2,这是我的输出

Enter age
1

1030455
1004
2144
2086
0

所以我想也许这句空白行以某种方式搞砸了我的AWK版画?是否有一种简单的方法可以在保留其他数据的同时忽略该空行?

2 个答案:

答案 0 :(得分:2)

这就是你如何使用awk来生成所需的值,作为输入中每个“行”块的每一行上的一组制表符分隔的字段:

$ cat tst.awk
BEGIN {
    RS="[*]+ [[:digit:]]+[]. row [*]+\n"
    FS="\n"
    OFS="\t"
}
NR>1 {
    sub(/\n$/,"")     # remove the trailing newline
    gsub(/\n\s+/," ") # compress all multi-line fields into single lines
    gsub(OFS," ")     # ensure the only OFS in the output IS between fields

    delete n2v
    for (i=1; i<=NF; i++) {
        name = gensub(/:.*/,"","",$i)
        value = gensub(/^[^:]+:\s+/,"","",$i)
        n2v[name] = value
    }

    if (n2v["Time"]+0 > age) {  # force a numeric comparison
        print n2v["Time"], n2v["Id"], n2v["Command"], n2v["State"]
    }
}

$ awk -v age=2000 -f tst.awk file
1030455 1       Connect Waiting for master to send event

如果目标年龄已经存储在shell变量中,则只需从同名的shell变量中初始化awk变量:

$ age="2000"
$ awk -v age="$age" -f tst.awk file

以上使用GNU awk进行多字符RS(您已经拥有),gensub()\sdelete array

当你说“并将这些参数中的每一个存储到一个不同的变量或数组中”时,它可能意味着其中一件事情,所以我会把那部分留给你,但你可能会找到类似的东西:

arr=( $(awk '...') )

awk '...' |
while IFS="\t" read -r Time Id Command State
do
    <do something with those 4 vars>
done

但到目前为止,最可能的情况是你根本不想使用shell而只是留在awk中。

记住 - 每次你在shell中编写一个循环只是为了操作文本你都有错误的方法。 UNIX shell是一个可以从中调用UNIX工具的环境,用于常规文本操作的UNIX工具是awk

在您编辑问题以告诉我们有关您的问题的更多信息之前,我们无法从这一点猜出正确的解决方案。

答案 1 :(得分:1)

在第一级,您拥有用于运行任何其他子进程的shell。从子进程内部修改父项环境是不可能的。当您运行bash脚本文件(正确+x)时,它会被生成为新进程(子进程)。它可以设置它自己的环境但是当它结束它的实时时你会回到原来的(父)。

您可以在bash上设置一些变量,并将export设置为它的环境。它将由它的孩子继承。但是它不能在相反的方向上完成(父亲不能从其子女继承)。

如果您希望在当前bash的上下文中从脚本文件执行某些命令,您可以source脚本文件。 source ./your_script.sh. ./your_script.sh会为您做到这一点。

如果你需要运行awk为你过滤一些数据并将结果保存在bash中,你可以这样做:

awk ... | read foo

这适用于read是shell buildin函数而不是外部进程(检查type readhelphelp readman bash以自行检查)

或:

foo=`awk ....`

您可以使用许多其他结构。无论您使用什么bash脚本,请将您的代码与bash pitfalls webpage进行比较。