【问题标题】:Using AWK and setting results to bash variables/arrays?使用 AWK 并将结果设置为 bash 变量/数组?
【发布时间】:2015-02-08 06:40:17
【问题描述】:

我有一个文件从 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 中使用/打印它们。

问题是,我对 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}}'

文件“数据”包含我上面粘贴的块。如果输入的“年龄”小于数据文件中的时间参数(在我的 awk 代码中为 $4),代码应该返回 ID 参数,但它什么也不返回。

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

Enter age
1

1030455
1004
2144
2086
0

所以我在想也许那个空白行会以某种方式弄乱我的 AWK 打印?有没有一种简单的方法可以在保留我的其他数据的同时忽略该空白行?

【问题讨论】:

  • 将输出粘贴到问题中,用鼠标标记,然后使用工具栏中的{} 工具将其标记为文字代码。
  • awk 不能直接设置 shell 变量。您可以做的是将awk 的输出通过管道传送到外壳while read var1 var2 var3 循环。
  • 嘿,谢谢,太棒了:)
  • 虽然我并没有真正理解你的解决方案,你能详细说明一下吗?
  • SO 不是免费的编码服务,我们不会为您编写代码。你需要做一些尝试来解决它。如果您无法使其正常工作,请发布您的代码,我们会尽力帮助您修复它。

标签: linux bash awk


【解决方案1】:

这就是您如何使用 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

在您编辑您的问题以告诉我们更多有关您的问题之前,我们无法猜测从此时起正确的解决方案是什么。

【讨论】:

    【解决方案2】:

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

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

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

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

    awk ... | read foo
    

    这是因为read 是shell 内置函数而不是外部进程(请检查type readhelphelp readman bash 自行检查)。

    或:

    foo=`awk ....`
    

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

    【讨论】:

    • 处理空行的一种简单(但效率不高)的方法是strings
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    • 2013-03-22
    • 1970-01-01
    • 2018-06-16
    • 1970-01-01
    相关资源
    最近更新 更多