bash一元运算符预期错误

时间:2017-08-07 18:06:17

标签: bash grep

这是我提出的脚本

#!/bin/bash

expression=$1
field=$2
if [ -z "$expression" ]; then
echo "expression is missing"
exit 1
fi

if [ -f /home/miked/table ]; then
  if [ -f table ] && [ grep "$expression table" ]; then
    grep "$expression" table | cut -d: -f${2:-3} | clipit
  else
    echo "no match found"
  fi
else
  echo "there is no table file"
fi

事实上,我知道如何解决它,但我不知道为什么 它是固定的。

如果删除grep"之间的空格,一切正常,我似乎无法理解原因。

如果我直接对命令行执行grep something file,那么它的工作正常。为什么要将grep粘贴到脚本中的"

3 个答案:

答案 0 :(得分:2)

您不需要在方括号内包含grep调用。 [test命令的别名(一般情况下,大多数shell使用内置复制)。您可以使用man test查看该命令的语法。你想要做的是检查某个文件中是否存在$expression table,所以你需要把它写成:

#!/bin/bash

expression="$1"
field="$2"
if [ -z "$expression" ]; then
  echo "expression is missing"
  exit 1
fi

if [ -f /home/miked/table ]; then
  if [ -f table ] && grep "$expression table"; then
    grep "$expression" table | cut -d: -f${2:-3} | clipit
  else
    echo "no match found"
  fi
else
  echo "there is no table file"
fi

但是您的脚本存在更多问题。

  1. 您将错误打印到stdout而不是stderr,这会使您在将脚本的输出传递给其他工具时隐藏错误,而应使用echo "error" >&2,理想情况下使用单独的函数。
  2. 您只将1个参数传递给grep,我认为应该有2个:grep "$expression" table
  3. 您的第一次grep来电也会打印到stdout,我相信您希望超越该号码,因此请使用-q标志。
  4. 最好启用"退出错误"使用set -e和"退出管道错误"使用set -o pipefail
  5. 您不使用外部文件,因此您可以删除该项目的检查。
  6. 您不使用$field变量。
  7. 使用guard clausule而不是if来进行致命错误检查,因为这样可以更轻松地重构脚本。
  8. 所以整个文件可以写成:

    #!/bin/bash
    
    set -eo pipefail
    
    perror() {
      echo "$1" >&2 && exit 1
    }
    
    expression=$1
    field=${2:-3}
    file=${3:table}
    
    [ -z "$expression" ] || perror "expression is missing"
    [ -f "$file" ] || perror "there is no '$file' file"
    
    grep "$expression" "$file" | cut -d: -f"${field}" | clipit || perror "no match found"
    

答案 1 :(得分:0)

这里根本不需要[ ]。你对grep的退出状态感兴趣,它已经给你一个;要禁止输出,可以使用-q选项:

if [ -f table ] && grep -q "$expression" table; then

文件名也不应该在引号内。

如果您在没有任何测试的情况下使用[ ],则默认为-n:“如果字符串不为空,则为true”。这个测试需要一个参数,这就是为什么它如果你删除空间似乎适合你:它只是检查字符串grep$expression table是否扩展为非零,并且它总是。

答案 2 :(得分:0)

有很多事情可以解决这个问题,你的主要问题是以下几行:  if [ -f table ] && [ grep "$expression table" ]; then

您已经测试过" table"存在,所以你再次这样做,一旦成功,正在评估表达式[ grep "$expression table" ],它被分解为'[' grep 'expression table' ']',这基本上没有任何意义。

你应该使用$()来评估出现的次数,或者像本杰明所提到的那样,如果这就是你想要的,那就完全跳过它。

我会建议这样的事情

#!/bin/bash
expression=$1
field=$2
table_file=/home/miked/table
if [ -z "$expression" ]; then
    echo "expression is missing"
    exit 1
fi

if [ -f $table_file ]; then
    if [ $(grep -q "$expression $table_file") -gt 0 ]; then
        grep "$expression" $table_file | cut -d: -f${2:-3} | clipit
    else
        echo "no match found"
    fi
else
    echo "there is no table file"
fi

请注意我们如何仍在使用测试,这可以简化为:

#!/bin/bash
expression=$1
field=$2
table_file=/home/miked/table
if [ -z "$expression" ]; then
    echo "expression is missing"
    exit 1
fi

if [ -f $table_file ]; then
    grep -q $expression $table_file && grep "$expression" $table_file | cut -d: -f${2:-3} | clipit || echo "no match found"
else
    echo "there is no table file"
fi