【问题标题】:Awk syntax error when command is executed through a shell script however the command works fine when executed from Linux bash shell通过 shell 脚本执行命令时出现 Awk 语法错误,但是从 Linux bash shell 执行命令时可以正常工作
【发布时间】:2019-03-26 09:03:57
【问题描述】:

我正在运行这个命令

awk '{print "Removing " ORS $0;system("rm " $0 ORS  " if [ $? -eq 0 ]" ORS "then" ORS "echo file  " $0 " has been removed." ORS "fi")}' <(cat /tmp/findo)

在 bash 上,该命令有效,但是当从 shell 脚本执行时,它会引发潜在错误

这是示例,您可以查看“第 23 行错误”

# sh -x rvarlog_util.sh
+ findout=/tmp/findout
+ '[' -e /tmp/findout ']'
++ du -sm /var/log
++ awk '{print $1+0}'
+ cdu=2372
++ awk '{print $1+0}'
++ grep total
++ du -m --max-depth=1 -c -m -x /var/log/messages /var/log/messages-20190310 /var/log/messages-20190323-1553338190.gz /var/log/messages-20190324-1553424406.gz /var/log/messages-20190324-1553456095.gz /var/log/messages-20190324-1553456293.gz /var/log/messages-20190324-1553457237.gz /var/log/messages-20190324-1553457268.gz /var/log/maillog-20190324-1553456095.gz /var/log/boot.log /var/log/audit/audit.log /var/log/audit/audit.log-20190311-1552325090.gz /var/log/puppetlabs
+ fusage=2258
rvarlog_util.sh: line 23: syntax error near unexpected token `('
rvarlog_util.sh: line 23: `awk '{print "Removing " ORS $0;system("rm " $0 ORS  " if [ $? -eq 0 ]" ORS "then" ORS "echo file  " $0 " has been removed." ORS "fi")}' <(cat /tmp/findo)'

【问题讨论】:

  • awk '{print "Removing " ORS $0;system("rm " $0 ORS" if [ $? -eq 0 ]" ORS "then" ORS "回显文件 "$0" 已被删除。 " ORS "fi")}'
  • 查看我上面评论中的链接,详细了解如何使上面的代码正确显示。
  • 好的,谢谢。让我格式化。
  • 问题几乎肯定出在你没有向我们展示的 shell 脚本的前几行,例如缺少的报价。发布重现错误的minimal reproducible example shell 脚本。顺便说一句,使用 shell 调用 awk 调用系统调用 shell 调用 rm 是一个糟糕的主意 - 只需直接从 shell 调用 rm。

标签: bash shell awk


【解决方案1】:

@Ibraheem 有正确的解决方案,但到目前为止没有人发现问题。那是您正在使用进程替换 (&lt;(cat /tmp/findo)),但使用 sh 而不是 bash 运行脚本。进程替换并非在所有 shell 中都可用(甚至 bash,当它被调用为“sh”时)。

有几种方法可以解决这个问题,我建议两者都做(因为它们本身就是好主意):

  • 不要使用&lt;(cat somefile),使用普通重定向,例如&lt;somefile。进程替代的cat 命令是一种过于复杂、脆弱且效率低下的文件读取方式。

  • 给脚本一个适当的 shebang 行(#!/bin/bash#!/usr/bin/env bash),使其可执行(chmod +x rvarlog_util.sh),然后通过输入其路径(./rvarlog_util.sh)直接运行它,而不是显式指定外壳(shbash)。一般来说,脚本应该“知道”它是为哪个 shell 编写的,并且覆盖它(通过在运行时显式指定 shell)是一个坏主意。

【讨论】:

  • 相当多的 shell 支持 &lt;(command),实际上,不仅仅是 bash。 (不过,在 Debian、Ubuntu 和许多其他 Linux 发行版上用于 /bin/sh 的破折号不是其中之一。)
  • @Shawn 哇,我不知道,但至少zshksh 93 都支持进程替换。我将编辑我的答案以更正此问题。
【解决方案2】:

从您的 awk 命令中,我了解到您正在尝试删除在 /tmp/findo 文件中找到名称的文件,对吗?然后用下面的代码替换您的 awk 命令并查看它是否有效,但请确保 /tmp/findo 中的文件名包含您尝试删除的所需文件的绝对路径

while read -r files
do
  rm "$files" 
  if [ $? -eq 0 ] 
  then
     "echo $files has been removed."
  fi
done < /tmp/findo

【讨论】:

  • 我建议在两次使用 $files 时双引号(对于 echo 命令,双引号整个字符串)。此外,您可以通过直接测试rm 的结果来简化它:if rm "$files"
  • 或更简单的:xargs -d'\n' rm -v &lt;/tmp/findo
  • @Wiimm 这个班轮完成了这项工作,非常感谢
  • @ronythomas 欢迎您,如果这是您所需要的,您可以接受答案,
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-01
  • 2015-04-29
  • 2015-11-01
  • 2019-11-06
  • 2023-03-06
  • 1970-01-01
相关资源
最近更新 更多