【问题标题】:AWK - input variable to pattern from SHELLAWK - 从 SHELL 输入变量到模式
【发布时间】:2015-01-02 18:02:43
【问题描述】:

我想使用 awk 从文件中提取文本,它基本上可以正常工作,但我想使用变量使其动态化以查找模式。

它应该如何工作:

文件 test_input 包含(顺便说一句:从 HP DP omnimm -show_locked_devs 提取)

Type:     Device
Name/Id:  Drive1
Pid:      28405
Host:     Host1

Type:     Cartridge
Name/Id:  Lib1
Pid:      28405
Host:     Host1
Location: 47
...
  • 获取 Drive1 的“Pid”编号 => 命令查找模式 (Drive1) 并显示文件 test_input (28405) 中的下一行

cat test_input | awk 'c&&!--c;/Drive1/{c=1}'| awk '{print $2}' 28405

  • 获取“位置”编号 => 查找所有“Pid”编号并显示每个匹配项的下 2 行(记录),然后使用 grep 过滤输出中的“位置”并显示第二个字段 (47)

cat test_input | awk 'c&&!--c;/28405/{c=2; print $0}'| grep Location | awk '{print $2}' 47

我注意到 AWK 中的双引号可以处理 SHELL 变量,但是当我在脚本中使用 SAME 命令时,我收到错误消息“awk:无法正确解析语句。”

DRIVE=Drive1;cat test_input | awk "c&&!--c;/$DRIVE/{c=1}" | awk '{print $2}' 28405

如果您对如何从 SHELL 获取工作变量有一些提示,请告诉我。 我也知道我的命令和重定向可能很复杂,但我不是脚本大师 :)

【问题讨论】:

  • 请。不要使用cat file|awk ...,应该是awk '' file。并且在一个管道中使用多个awkgrep通常可以简化为单个awk
  • @Jidder:你的建议至少少了一个笑脸! ;)
  • 只对变量进行双引号,其他所有内容保持单引号。像这样:awk 'c&&!--c;/'"$DRIVE"'/{c=1}'
  • 这里有大约 1e3 个关于将变量传递给 awk 的问题。请搜索...

标签: shell variables awk scripting


【解决方案1】:

如果您只需要使用环境变量,那么您可以使用 ENVIRON 内置哈希。如果您想将参数传递给,您可以使用-v 选项。

两个例子:

cat >inputfile <<EOT
aaa
bbbxxx
xxxccc
ddd
EOT

VAR=xxx
awk -vVAR="$VAR" '$0~VAR {print ENVIRON["USER"]":"$0}' inputfile

我添加了示例inputfile 的创建。

据我所知,在某些 版本中,-vVAR 之间需要一个空格。

如果我建议您在整个脚本行周围使用' 而不是"。如果你大量使用,它会让生活变得更轻松。

输出:

myuser:bbbxxx
myuser:xxxccc

如果我理解得很好,您需要在非“设备”块中收集所有设备和所有位置的名称。我假设时钟以标签Type 开头,并且标签顺序始终相同。如果没有,请。通知我。基于这些假设,我的代码如下所示:

awk '$1=="Type:"{dev=$2=="Device"}
dev && $1=="Name/Id:"{name=$2}
dev && $1=="Pid:"{pids[name]=$2}
!dev && $1=="Pid:"{pid=$2}
!dev && $1=="Location:"{locs[pid]=$2}
END {
    for(i in pids) {
        pid = pids[i];
        print i"\t"(pid in locs ? locs[pid] : "None");
    }
}
' inputfile

它会填充 pidslocs 哈希,然后打印在 pids 哈希中找到的所有设备名称以及属于此 pid 的位置(如果找到)。

输出:

Drive1  47

当然,如果位置总是在设备块之后,则可以在找到位置后立即打印该行。所以END 部分可以被删除。

【讨论】:

    【解决方案2】:

    不清楚你想要什么,但也许是这样:

    $ cat tst.awk
    BEGIN{ RS=""; FS="[:[:space:]]+" }
    {
        for (i=1;i<=NF;i+=2)
           name2val[$i] = $(i+1)
    }   
    (name2val[key] == val) && (tgt in name2val) {
        print name2val[tgt]
    }
    $
    $ awk -v key="Name/Id" -v val="Drive1" -v tgt="Pid" -f tst.awk file
    28405
    $
    $ awk -v key="Pid" -v val="28405" -v tgt="Location" -f tst.awk file
    47
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-16
      • 2018-04-09
      • 2020-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多