【问题标题】:How to increment a shell variable in an awk action如何在 awk 操作中增加 shell 变量
【发布时间】:2014-06-02 02:22:15
【问题描述】:

我的 shell 脚本是这样的:

#!/bin/bash

global_var=0

func() {
 awk '$1 ~/^pattern/ {global_var=$((global_var+1))}' $1
}

func input_file_name

我想在awk 操作中增加全局(shell)变量global_var。怎么做?正常的 shell 样式递增似乎不起作用。

【问题讨论】:

  • awk 命令中,访问变量时不需要使用$
  • @WKPlus: 一般情况下是这样,但这里的问题是尝试从 awk 程序内部访问 shell 变量(使用shell 语法,但这是次要问题)。
  • 问题不仅在于从awk 脚​​本中访问shell 变量,还在于尝试从awk 脚本中修改shell 变量。

标签: linux bash shell awk


【解决方案1】:

试试这个:

func() {
 awk '$1~/^pattern/ {++awk_var} END {print awk_var+0}' "$1"
}

shell_var=$(func input_file_name)

shell 和 awk 是独立的世界,您应该这样对待它们(*)(实际上,您已经在这样做了,将您的 awk 程序包含在引号,防止shell扩展你的akw程序中的任何shell变量引用字符串)。

因此,使用awk[-internal] 变量来执行您的计数(awk_var,并在处理完输入文件后将其输出(在END 块中,使用printawk 变量输出到stdout - +0 部分是为了确保在未找到匹配项的情况下输出默认为0。)

请注意,awk 变量通常不需要显式初始化,因为它们在数字和布尔上下文中默认为 0,在字符串上下文中默认为 ""(空字符串)。

另请注意,awk 有自己的语法,而 $((...)) 等用于算术扩展的 shell 结构不适用。一般awk变量只按名称引用(没有$前缀),可以直接应用++等算术运算。

在 shell 中使用 命令替换 - $(...) - 然后您可以捕获来自 awk 命令的输出

在您的具体情况下,您无需将变量值传入awk 程序,但如果您需要这样做,您可以使用awk 的一个或多个实例s -v 选项;例如:awk -v awk_var="$shell_var" ...

在 shell (bash) 方面,如果您想添加 awk 的输出到 shell 变量而不是仅仅分配它: p>

declare -i shell_var                # make sure variable is an integer
shell_var+=$(func input_file_name)  # add function's output to existing value

(*) shell 和awk 具有完全独立的命名空间,它们之间没有直接的交互方式:awk 没有shell 变量的概念,shell 没有awk 的概念变量。

技术上可行,但不建议将 shell 变量 VALUES 集成到 awk 程序中 - 通过使用 double-带引号的字符串来表示您在其中引用 shell 变量 VALUESawk 程序,然后在字符串之前由 shell ONCE 扩展这些变量作为程序传递给awk
你不能做的是从awk 程序中修改 shell 变量。

因为关于awk 程序的哪些部分由shell 预先解释与哪些部分由awk 稍后解释(其中'$ 也有特殊含义)很快变得复杂, 最佳方法是:

  • 使用引用的字符串来表示awk程序,以保护它不被shell解释
  • 如果需要在中传递值,请使用-v 选项的实例
  • 如果需要传递某些内容,请从 awk 打印到 stdout,然后使用命令替换或重定向通过 shell 捕获它。

【讨论】:

  • 如果你export global_var,那么你可以从ENVIRON["global_var"]初始化awk_var。并不是说这是一个好主意,特别是因为它是单程旅行,但 awk 程序至少可以访问环境变量。也许这只是比有用更令人困惑。
  • 不确定您为什么使用 printf 而不是 print,但无论如何它可能只是 awk '$1 ~/^pattern/ {++awk_var} END {print awk_var+0}'。 +1 的详细解释。
  • @rici:这是一个有趣的替代方案,值得了解,但由于它是单向街道,您不妨使用-v ...
  • @EdMorton 谢谢,并感谢+0 提示-已添加到答案中。我使用printf 知道结果将被捕获在一个变量中,但我同意这里可能会造成混淆(并且在没有格式字符串的情况下通常不太安全),所以我切换到print。跨度>
  • 我认为最后一个语句应该是(( shell_var += $(func input_file_name) ))。否则 awk 应该有 -v "awk_var=$shell_var".
猜你喜欢
  • 2012-02-25
  • 2012-03-04
  • 2012-11-26
  • 1970-01-01
  • 2018-05-06
  • 2013-08-06
  • 2017-03-05
  • 2014-01-20
  • 1970-01-01
相关资源
最近更新 更多