【问题标题】:Grep issues with if statement in shell script与 shell 脚本中的 if 语句有关的 Grep 问题
【发布时间】:2017-05-21 21:16:28
【问题描述】:

我在 shell 脚本 if 语句中遇到了 tailgrep 的问题。如果我在 shell 中运行 tail -5 mylog.log | grep -c "Transferred: 0",它会正常运行,但是在这个 shell 脚本中的 if 语句:

# Parse log for results
if [ tail -1 "$LOGFILE" | grep -c "Failed" ] ; then
        RESULT=$(tail -1 "$LOGFILE")
elif [ tail -5 "$LOGFILE" | grep -c "Transferred:            0" ] ; then
        RESULT=""
else
        RESULT=$(tail -5 "$LOGFILE")
fi

我明白了

... [: missing `]'
grep: ]: No such file or directory

两个 grep 行。

这显然与关闭 ] 被视为 grep 的一部分(因此丢失)有关,但我使用了正确的空格,所以我无法弄清楚发生了什么?我在这里做错了什么?

谢谢, PJ

【问题讨论】:

  • [ ] 不是if 语法的一部分。这是一个单独的命令
  • 坦率地说,这只是效率低下——它至少调用了两次tail。调用一次然后在本机 bash 中测试结果要好得多。
  • 顺便说一句,在此处提问之前,请考虑通过shellcheck.net 运行您的代码。
  • 我如何通过只调用一次tail 来解决这个问题?顺便说一句,感谢 shellcheck.net。
  • 我已经扩展了我的答案,以展示一种只有一个 tail 调用(并且根本没有 grep 调用)的方法。

标签: bash shell if-statement grep tail


【解决方案1】:

立即问题/立即修复

取出括号。

if tail -1 "$logfile" | grep -q "Failed" ; then

[ 不是if 语法的一部分。相反,它是名为 test 的命令的同义词(通常可用作 shell 内置和外部二进制文件,如 /bin/test/usr/bin/test)。

因此,您的原始代码正在运行 [ tail -1 "$logfile",并将其结果通过管道传输到 grep -q "Failed" ]。第一个 [ 失败了,因为它没有看到结尾 ]——当使用该名称而不是名称 test 调用时这是强制性的——并且还因为它的参数不是它所知道的测试如何解析;而第二个grep 不知道] 是什么意思,它正在尝试查找具有该名称的文件。


其他说明

尝试尽可能少地运行外部命令——例如tail。启动成本非常高。

考虑以下,tail 只运行一次:

#!/bin/bash
#      ^^^^- IMPORTANT: bash, not /bin/sh

last_5_lines="$(tail -5 "$logfile")"
last_line="${last_5_lines##*$'\n'}"
if [[ $last_line = *Failed* ]]; then
  result=$last_line
elif [[ $last_5_lines =~ 'Transferred:'[[:space:]]+'0' ]]; then
  result=''
else
  result=$last_5_lines
fi

【讨论】:

  • 感谢详细解释!
  • 顺便说一句,解释全小写变量——见pubs.opengroup.org/onlinepubs/009695399/basedefs/…;全大写名称用于对 shell 或操作系统有意义的变量,而名称中至少包含一个小写字符的变量保留供应用程序使用。这只是环境变量的黑色字母 POSIX,但由于设置常规 shell 变量将覆盖任何类似命名的环境变量,因此如果您想避免冲突,该约定也必然适用于它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
  • 1970-01-01
  • 1970-01-01
  • 2021-07-26
  • 1970-01-01
  • 2019-08-15
  • 1970-01-01
相关资源
最近更新 更多