3

我是 shell 脚本的新手,我的脚本似乎没问题,但是我在控制流程时遇到了问题。请有人指出我犯了什么愚蠢的错误。

#! /bin/sh

echo "Are you sure youx want to delete $1? Answer y or n"
read ans
echo $ans
if $ans = "y"|"Y"
then
    mv $1 /home/parallels/dustbin
    echo "File $1 has been deleted"
else echo "File $1 has not been deleted"
fi
4

4 回答 4

1

使您的 if 条件如下:

if [ "$ans" = "y" -o "$ans" = "Y" ]
于 2012-12-03T12:06:19.523 回答
1

您的脚本有一些问题。有些是严重的,有些则不那么严重。

一是问题严重。

正如大师建议的那样,您需要使用方括号来包围您的if状况。这是因为if只测试条件的输出,它不执行实际的字符串比较。传统上,一个名为 的程序(/bin/test也称为/bin/[)负责处理该问题。如今,该功能已内置到 shell 中,但/bin/sh仍然表现得好像它是一个单独的程序。

事实上,if当你使用方括号来表示你的情况时,你可以做一些有趣的事情。例如,if grep -q 'RE' /path/to/file; then很常见。该grep -q命令不发出任何输出,而只是返回由if.

第二个严重的问题是你正在呼应一个可能是也可能不是真的状态。我称这是一个严重的问题,因为......好吧,日志消息根本不应该做出虚假声明。如果 中的文件的权限错误$1,或者文件名包含空格,则您的mv命令将失败,但消息将声称它没有。稍后再谈。

接下来,不太严重的问题。

这些主要是样式和优化的东西。

首先,read在大多数平台上都包含一个-p允许您指定提示的选项。使用它,您不需要包含echo命令。

其次,您的缩进使得很难看到if构造正在包装什么。在这么小的程序中,这不是一个大问题,但是随着您的成长,您真的希望遵循一致的标准。

第三,如果您使用case语句而不是if.

毕竟,这是我编写此脚本的方式:

#!/bin/sh

if [ "$1" = "-y" ]; then
  ans=y
  shift
elif [ -t 0 ]; then
  read -p "Are you sure you want to delete '$1' (y/N) ? " ans
fi

case "$ans" in
  Y*|y*)
    retval=0
    if [ -z "$1" ]; then
      retval=64
      echo "ERROR: you didn't specify a filename." >&2
    if [ ! -f "$1" ]; then
      retval=66
      echo "ERROR: file '$1' not found!" >&2
    elif mv "$1" /home/parallels/dustbin/; then
      echo "File '$1' has been deleted" >&2
    else
      retval=$?
      echo "ERROR: file '$1' could not be deleted!" >&2
    fi
    ;;
  *)
    echo "ABORT: file '$1' has not been deleted" >&2
    retval=4
    ;;
esac

exit $retval

除了上面提到的之外,以下是此代码段中的一些内容:

  • [ "$1" = "-y" ]- 如果用户指定了一个-y选项,那么我们的行为就好像问题是用“是”回答的。
  • [ -t 0 ]- 这测试我们是否在交互式终端上。如果我们是,那么用 提问是有意义的read
  • Y*|y*)- 在 case 语句中,这匹配任何以大写或小写“y”开头的字符串。因此,有效的肯定回答将是“Y”、“yes”、“yellow”等。
  • [ ! -f "$1" ]- 这将测试文件是否存在。您可以man testman sh查看 shell 中可用的各种测试。(-f可能不是最适合你的。)
  • >&2- 在一行的末尾,将其输出发送到“标准错误”而不是“标准输出”。这改变了管道、cron 等处理输出的方式。错误和日志数据通常被发送到 stderr,因此 stdout 可以专用于程序的实际输出。
  • mv "$1" ...- 文件名用引号括起来。这可以保护您,以防文件名中包含空格等特殊字符。
  • $retval- 此值来自对 中最接近的项目的最佳猜测man sysexits
  • retval=$?- 这是最近执行的命令的退出状态。在这种情况下,这意味着我们将mv的退出状态分配给变量$retval,因此如果mv失败,则整个脚本会报告失败的原因,就目前mv而言。
于 2012-12-04T05:39:59.833 回答
0

以下是包含错误处理的完美代码

#!/bin/sh

echo "Are you sure you want to delete $1? Answer y or n"
read ans
echo $ans

if [ $ans == "y" ] || [ $ans == "Y" ]
then
    if [ -f $1 ]
    then
           mv $1 /home/parallels/dustbin
           echo "File $1 has been deleted"         
    else
           echo " File $1 is not found"
    fi
else 
    echo "File $1 has not been deleted"
fi
于 2012-12-04T13:11:46.227 回答
0

您还可以将用户响应转换为任何一种情况,然后检查相应的情况,例如

read ans
ans=${ans,,}  # make 'ans' lowercase, or use ${ans^^} for making it uppercase
if [ "$ans" = "y" ]
then
   ....
fi
于 2012-12-03T15:48:38.077 回答