【问题标题】:Make Bash script exit and print error message if users invoke the script incorrectly如果用户错误地调用脚本,使 Bash 脚本退出并打印错误消息
【发布时间】:2012-10-09 14:49:40
【问题描述】:

需要的脚本是

#!/bin/bash

# Check if there are two arguments
if [ $# -eq 2 ]; then
   # Check if the input file actually exists.
   if ! [[ -f "$1" ]]; then
     echo "The input file $1 does not exist."
     exit 1
   fi
else
   echo "Usage: $0 [inputfile] [outputfile]"
   exit 1
fi

# Run the command on the input file
grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" "$1" > "$2"

编辑,脚本已更改为

grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" $*
if [ ! -f "$1" ]; then

  echo 'Usage: '
  echo
  echo './Scriptname inputfile > outputfile'
  exit 0

fi

在没有参数的情况下调用脚本不会出错并且是空白

Usage: 

./Scriptname inputfile > outputfile

我有一点代码

grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" $*

此代码提取包含单个单词的行并将输出泵送到新文件,例如

This is a multi word line
this
the above line is not
now
once again wrong

输出将是

This
now

代码有效,用户使用./scriptname file > newfile调用代码

但是,如果用户错误地调用脚本,我会尝试扩展代码以向用户提供错误消息。

对于错误消息,我正在考虑回显scriptname file_to_process > output_file 之类的内容。

我试过

if [incorrectly invoted unsure what to type]
echo $usage

exit 1
Usage="usage [inputfile] [>] [outputfile]

但是我运气不佳。如果我只使用脚本名称调用,代码会运行但什么也不做。此外,如果我只使用脚本名称和输入文件调用脚本,它将输出结果而不是退出并显示错误消息。

我尝试过的其他方法是

if [ ! -n $1 ]; then

  echo 'Usage: '
  echo 
  echo './Scriptname inputfile > outputfile'
  exit 0

fi

鉴于我目前收到的回复,我现在的代码是

#!/bin/bash
grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" $*
if [ ! -f "$1" ]; then

  echo 'Usage: '
  echo 
  echo './Scriptname inputfile > outputfile'
  exit 0

fi

在没有输入文件的情况下调用脚本时,脚本什么也不做,必须用 ctrl+c 中止,仍然试图获得调用消息的回显。

【问题讨论】:

  • 你使用的是/bin/bash还是/bin/sh
  • 在命令行使用"$@"而不是$*;用空格保留文件名参数中的空格。如果您在表达式前面使用grep -P -e "...your regex..."-e,则用户可以在命令行上键入-n-l 作为选项,grep 将适当地修改其行为。 (在使用 GNU getopt() 来置换参数的系统上,您可能不需要指定 -e;我不喜欢那个功能。)
  • 好吧,我现在将更改 $@
  • 使用[ -z "$1" ] 代替[ ! -n $1 ]。还将 grep 放在参数计数测试之后,而不是之前。如果它在之前并且没有参数,它将坐在那里等待您在标准输入上输入输入。要进行实验,请在命令行中尝试grep x,不带文件名,然后在其中键入一些带和不带 x 的行,然后 ^D 退出。

标签: bash error-handling multiplicity


【解决方案1】:

当您调用像./scriptname file > newfile 这样的脚本时,shell 将file 解释为./scriptname 的唯一参数。这是因为> 是标准输出重定向操作符。

我想提出 2 个可能的替代方案:


备选方案 1: 也许您可以尝试像这样将其作为 1 个参数传递?
./scriptname 'file > newfile'

在这种情况下,检查格式的一种方法是

#!/bin/bash

# Check if the format is correct
if [[ $1 =~ (.+)' > '(.+) ]]; then
  # Check if the input file actually exists.
  if ! [[ -f "${BASH_REMATCH[1]}" ]]; then
    echo "The input file ${BASH_REMATCH[1]} does not exist!"
    exit 1
  fi
else
  echo "Usage: $0 \"[inputfile] [>] [outputfile]\""
  exit 1
fi

# Redirect standard output to the output file
exec > "${BASH_REMATCH[2]}"
# Run the command on the input file
grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" "${BASH_REMATCH[1]}"

注意:如果您正在检查参数是否有效,通常最好在检查完成后才运行命令。


备选方案 2: 传递 2 个参数,例如

./scriptname file newfile

脚本如下所示

#!/bin/bash

# Check if there are two arguments
if [ $# -eq 2 ]; then
   # Check if the input file actually exists.
   if ! [[ -f "$1" ]]; then
     echo "The input file $1 does not exist."
     exit 1
   fi
else
   echo "Usage: $0 [inputfile] [outputfile]"
   exit 1
fi

# Run the command on the input file
grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" "$1" > "$2"

【讨论】:

  • 谢谢,唯一的问题是输出是Usage: $0 [inputfile] [>] [outputfile] 所以我只需要在最后的 fi 和 exit 0 之后添加另一个正确吗?
  • 脚本将运行grep,如果grep成功运行,脚本将以状态0退出,因此脚本中实际上不需要exit 0(如果我理解你是说...)
【解决方案2】:

我会为此使用parameter expansion

inputfile=${1:?Usage: $(basename $0) inputfile > outputfile}

如果脚本在没有参数的情况下调用(即$1 未设置),${var:?error message} 扩展会导致 shell 显示给定消息的错误并退出。否则第一个参数分配给$inputfile

【讨论】:

  • 好问题 - 对于简单的脚本,它是一种优雅的单行解决方案,对我来说效果很好,谢谢!
  • 如果您需要更清楚地格式化用法,您似乎也可以将错误消息拆分为脚本中的行,并且输出将反映相同的换行符
【解决方案3】:

尝试在$1周围添加双引号并使用-f检查是否存在并且是正常文件:

if [ ! -f "$1" ]; then

  echo 'Usage: '
  echo 
  echo './Scriptname inputfile > outputfile'
  exit 0

fi

【讨论】:

  • 好吧,我厌倦了使用 grep -P "^[\s]*[0-9A-Za-z-]+.?[\s]*$" $* if [ ! -f "$1" ]; then echo 'Usage: ' echo echo './Scriptname inputfile > outputfile' exit 0 fi 调用它时的代码只是坐在那里什么也没做,我尝试只使用脚本名称调用,我在使用代码时错过了什么。
【解决方案4】:

您还可以使用$#cat 使用消息来检查参数计数:

if [ ! $# -eq 1 ]; then
cat << EOF
    Usage:

    $0 'input_file' > output_file
EOF
    exit 1
fi

【讨论】:

  • [ $# -ne 1 ]代替[ ! $# -eq 1 ]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-23
相关资源
最近更新 更多