【问题标题】:"awk" is not processing shell variables as expected“awk”未按预期处理 shell 变量
【发布时间】:2019-12-08 13:50:58
【问题描述】:

我正在从日志文件中过滤特定文本。这里的问题是 awk 没有处理 shell 变量。但在文件名上工作正常。 每当有新日志出现时,我都会在循环中使用“new_log=tail -n5 alerts.log”将日志文件中的新日志条目存储在 shell 变量中,然后,

Level_no=`awk '{FS="Rule: "}{print $2}' "$new_log" | sed '/^$/d' | awk '{FS=" "}{print $3}' | sed 's/)//g'

输出:

awk: fatal: cannot open file `** Alert 1564460779.1380: mail  - ossec,syscheck
* New Log starts from ** Alert 1564460779.1380: mail  - ossec,syscheck *`

当我使用文件名而不是 shell 变量在终端中运行时,上述命令运行良好,如下所示:

awk '{FS="Rule: "}{print $2}' logs_mining | sed '/^$/d' | awk '{FS=" "}{print $3}' | sed 's/)//g'

但是如果我将新的日志条目存储在另一个文件中并从那里处理,它的性能问题。

所以我研究得越来越多,开始了解 awk 变量……这是我的 shell 脚本……

Level_no=`awk -v var="$new_log" '{FS="Rule: "}{print $2}' var | sed '/^$/d' | awk '{FS=" "}{print $3}' | sed 's/)//g'

然后输出说

awk: fatal: cannot open file `var' for reading (No such file or directory)

实际结果应该是成功执行 awk 脚本。

【问题讨论】:

  • 什么包含$new_log?你能给我们echo "$new_log"的结果吗?
  • awk 的第二个参数是文件名,但$new_log 不包含文件名,它包含您从文件中提取的行。
  • @MuhammadShayaan :除了在您的第一次尝试中,new_file 确实 not 包含您发布的内容(正如我们从错误消息中看到的那样),即使它包含tail -n5 alerts.log 如您所说,我怀疑您是否有此名称的文件。我建议你在set -x 下运行你的代码。顺便说一句,您的命令缺少结束反引号。并且:反引号已过时;建议改用$(...)
  • 你是对的。 @Barmar $new_log 包含从文件中提取的行
  • awk '{FS="Rule: "}{...}' sets FS after 它已经在第一条记录上使用它的默认值。我怀疑你想要awk 'BEGIN{FS="Rule: "}{...}'

标签: linux bash shell awk scripting


【解决方案1】:

如果new_log 包含您要处理的数据,而不是文件名,则需要将其通过管道传送到awk。您可以使用此处的字符串来执行此操作。

Level_no=`awk '{FS="Rule: "}{print $2}' <<<"$new_log" | sed '/^$/d' | awk '{FS=" "}{print $3}' | sed 's/)//g'`

也没有必要将输出传送到sed 和另一个awk,您可以在第一个脚本中完成所有操作。

Level_no=$(awk -F'Rule: ' '$2 != "" {split($2, a, " "); gsub(/)/, "", a[3]); print a[3]}' <<<"$new_log")

不过,您可能不需要该变量,只需将命令的输出通过管道传输到 awk:

Level_no=$(tail -n5 alerts.log | awk -F'Rule: ' '$2 != "" {split($2, a, " "); gsub(/)/, "", a[3]); print a[3]}')

【讨论】:

  • 虽然更好的解决方案是不在变量中输入。
  • 好点,添加了一个删除变量的变体。
  • 效果很好...非常感谢。 @Barmar
猜你喜欢
  • 2018-02-10
  • 2020-08-02
相关资源
最近更新 更多