【问题标题】:Nested if in shell scripting如果在 shell 脚本中嵌套
【发布时间】:2014-06-11 18:31:28
【问题描述】:

我想编写一个带有 1 个命令行参数(一个目录)的脚本,然后提示输入 2 个数字,然后它将打印出大小介于 2 个数字之间的任何文件(每个文件在不同的行中),这个是我的剧本

echo -n "Enter the first number: "
read a
echo -n "Enter the second, bigger number: "
read b
    if
 [ $b -lt $a ]
then
 echo 'The first number must be smaller'
else
 echo The files in $1 that are between $a and $b bytes are the following
 echo
 for var in 'ls $1'
 do
  if
   [ -f $var ]
  then
    size='ls -l $var | '{ print $5 }''
     if
      [ $size -le $b && $size -ge $a ]
     then
      echo $var is $size bytes
     fi
  fi
 done
fi

问题是在我输入数字后,它会打印出“文件...”,然后什么都没有。另外,我用vi编辑,但最后三行的颜色不太对(颜色应该和第一个“fi”匹配,但不是)。谁能告诉我出了什么问题?谢谢。

【问题讨论】:

  • 您需要一个“shebang”行作为脚本的最上面一行。您应该拥有#!/bin/ksh#!/bin/bash 或您从echo $SHELL 获得的任何值。并且您只需在设置了 shell 调试/跟踪选项的情况下运行此代码即可发现大部分问题。添加 set -vx 只是 echo -n ... 。调试会在执行之前显示每个代码块,以及带有前导 + 符号的代码块中被执行的每一行,其中包含变量的值。你应该看到$size 不是你想象的那样。祝你好运。
  • 为什么我需要那个 hashbang 行?我很快就读到了它,但仍然不明白我为什么需要它。非常感谢,我不知道有一个调试器:)
  • @NguyễnDuy 您应该包含#!/bin/??sh 行,实质上是声明运行脚本所需的shell。如果它与 good-old-bourne shell 兼容,您将使用 #!/bin/sh,但如果您使用仅在 zsh 或 bash 中可用的功能(内置),则应使用 #!/bin/bash 或 '#!/bin/ zsh` - 或其他任何东西。您还可以编写以 #!/usr/bin/perl 开头然后是 chmod +x myPerlScript 的 Perl 脚本之类的东西,并且您不必在文件上使用诸如 .pl 扩展名之类的废话。

标签: shell unix conditional-statements ls


【解决方案1】:

这里有几个问题,但我认为你遇到的一个问题是单引号字符 (') 用在几个应该使用反引号字符 (`) 的地方。这是一个微妙的印刷区别,所以有时以前没有遇到过的人不会意识到这种区别。在我的键盘上,您可以通过点击数字 1 左侧的键来获得一个反引号字符,它与波浪号 (~) 配对,但您的键盘可能不同。

反引号允许您将命令的输出分配给变量,例如:

my_variable=`ls - l` # <- uses backtick, assigns output of 'ls -l' command to $my_variable

#As opposed to:
my_variable='ls -l' # <- uses single-quote, makes $my_variable equal to the text "ls -l"

注意,如果您用反引号替换正确的单引号,这也将解决您的 vi 问题。

【讨论】:

  • 更好的是,使用更具视觉特色的$(ls -l) 而不是反引号。
【解决方案2】:

正如其他人所说,在命令中使用 shebang 并使用反引号。其他错误,ls -l $var | '{ print $5 }' 应该是 ls -l "$1$var" | awk '{ print $5 }'(缺少 awk 命令),并且在测试文件时,您应该使用文件的完整路径,例如 [ -f "$1$var" ],因为用户可能不在同一个目录中它们作为参数提供给脚本的路径。另一个问题是[ $size -le $b &amp;&amp; $size -ge $a ]。您不能那样使用&amp;&amp; 运算符,而是使用[ $size -le $b ] &amp;&amp; [ $size -ge $a ]

这些是我对您的代码所做的所有更改。希望它对你有用。

echo -n "Enter the first number: "
read a
echo -n "Enter the second, bigger number: "
read b
if [ $b -lt $a ]
then
  echo 'The first number must be smaller'
else
  echo The files in "$1" that are between "$a" and "$b" bytes are the following
  echo
  for var in `ls "$1"`
  do
    if [ -f $1$var ]
    then
      size=`ls -l "$1$var" | awk '{ print $5 }'`
      if [ $size -le $b ] && [ $size -ge $a ]
      then
        echo "$var" is "$size" bytes
      fi
    fi
  done
fi

【讨论】:

    【解决方案3】:

    您的直接问题是您在需要命令替换的地方使用了单引号。但是,这是迭代文件的错误方法。您应该改用模式匹配。你的for 循环应该是

    for var in $1/*
    do
      if [ -f "$var" ]
      then
        # Check 'man stat' for the correct format string on your system
        size=$(stat +%s "$var")
        if [ $size -le $b ] &&  [ $size -ge $a ]
        then
          echo $var is $size bytes
        fi
      fi
    done
    

    【讨论】:

      猜你喜欢
      • 2014-02-05
      • 2021-08-21
      • 2016-06-02
      • 2013-05-10
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多