传递条件语句时 awk 语句出现问题

传递条件语句时 awk 语句出现问题

我正在尝试根据条件计算文件中列的空记录。但条件不行。

  • 输入示例:固定宽度文件,
                 761128424607/22/20197611284246CAD052020DHH 0073578EKLAVY3
ELEKBAFXXL7900271761128424406/22/20197611284244CAD042020DKA 0038244EDITTU8                     
                 761128424606/22/20197611284246CAD052020DHH 0073578EKLAVY3                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
ELEKBAFXXL7900271761128424406/22/20197611284244CAD042020DKA 0038244EDITTU8
  • 代码
    RE='[[:space:]]{17}' awk -v m=1 -v p=17 -v r='&& substr($0,28,2)==06'
        $'BEGIN{re = ENVIRON["RE"]}{c = substr($0,m,p)}  c ~ "^(" re ")$" r  {N++}  END {print N+0}' <  input_file.txt
    
  • 所需的输出:1,因为文件中有 2 条记录为空,并且这 1 条记录满足条件substr($0,28,2)==06
  • 实际输出:0,这是错误的

答案1

这将通过让 shell 变量的内容在被调用来解释它r之前扩展成为 awk 脚本的一部分来完成您所要求的操作,但几乎可以肯定有一种更好的方法来完成您真正想做的事情awk:

$ r='&& substr($0,28,2)=="06"'
$ RE='[[:space:]]{17}' awk -v m=1 -v p=17 '
    BEGIN { re = ENVIRON["RE"] }
    { c = substr($0,m,p) } 
    c ~ "^(" re ")$" '"$r"' { N++ }
    END { print N+0 }
' file
1

如果你必须&& substr($0,28,2)=="06"在某个地方写,那么你为什么不把它写在 awk 脚本中而不是 shell 变量中就一点也不明显了——无论你想做什么,都必须有更好的方法。

答案2

awk ... r='&& substr($0,28,2)==06'
    '... c ~ "^(" re ")$" r  { ... } '

这看起来像是您正在尝试使用 awk 变量来动态构建条件?也就是说,使用 awk 变量的内容r作为 awk 语法的一部分。

我认为这行不通。在 awk 中,背对背值被视为字符串连接,因此会变成类似 的内容c ~ "^(" re ")$&& substr($0,28,2)==06",即它会将 的内容r作为正则表达式的一部分进行匹配。

例如,awk -v var=bar '$0 ~ "foo" var'将打印包含 的行foobar,即使变量包含&&等,它的工作原理也类似。

它可能也无法在任何其他编程语言中工作,因为代码和数据之间的分离几乎是理智和安全程序的要求。即使在 shell 中也不能这样工作。 (没有eval或这样的。)

只需完整地写出整个表达式即可。

答案3

通过一些更改,您可以让它输出预期的结果:

RE='[^[:space:]]' awk -v m=1 -v p=17 \
$'(r=substr($0,28,2)=="06")&&
(substr($0,m,p) !~ re) {N++}
BEGIN {re = ENVIRON["RE"]}
END {print N+0}' < input_file.txt

编辑:-

  • 将命令行上声明的 awk 变量 r 转换为$'...'代码块内。
  • 删除&&,将其转换为布尔值。
  • 坚持在和布尔条件&&之间。c ~ ...r
  • 将数字比较更改==06为字符串比较=="06"

答案4

使用 GNU awk,您可以使用FIELDWIDTHS变量来指定固定宽度字段的宽度:

gawk '($1!~/[^ ]/) && ($3=="06"){++c} END{print c+0}' FIELDWIDTHS='17 10 2 *' file

您可以尝试参数化 awk 脚本 – 一些尝试:

str=06 gawk -v FIELDWIDTHS='17 10 2 *' '
  ($1 !~ /[^ ]/) && ($3"" == ENVIRON["str"]) {
      ++c
  }
  END {print c+0}
' file
str=06 rexp='^ {17}$' gawk -v FIELDWIDTHS='17 10 2 *' -v rexp_col=1 -v str_col=3 '
  ($rexp_col ~ ENVIRON["rexp"]) && ($str_col"" == ENVIRON["str"]) {
      ++c
  }
  END {print c+0}
' file

相关内容