例一

例一

这个 Linux 程序应该打印 0 到 4。但是我无法在这段代码中找到错误。

#!/bin/sh

a=0

while [ $a -lt 5 ]
do
    echo $a
    a='expr $a + 1'
done

当我尝试运行它时,它显示“第 5 行:[:参数太多”。

答案1

您可以使用反引号进行命令替换

a=`expr $a + 1`

答案2

我提供了三个示例,前两个带有while循环,第三个带有until循环。第一个示例使用与原始示例非常接近的语法,第三个示例稍微复杂一些,因为它使用计数器最大值的动态设置和用于迭代一次传递一个单词(空格分隔的参数)的数组。现在这些是简单的示例,并且旨在仅用 Bash 脚本语言回答您的直接问题,如果您想要更高级的示例,请参阅我在 GitHub 上维护的脚本所附的链接,以获取其他技术向导中的嵌套循环示例。

例一

#!/usr/bin/env bash
let _counter=0
let _max="5"
while [ "${_counter}" -lt "${_max}" ]; do
    echo "${_counter}"
    let _counter=++
done
unset _counter
unset _max

运行示例一

./example_one.sh
1
2
3
4
5

示例二

#!/usr/bin/env bash
_arr_args=( "${@}" )
let _counter=0
let _max="${#_arr_args[@]}"
while [ "${_counter}" -lt "${_max}" ]; do
    echo "${_arr_args[${_counter}]}"
    let _counter=++
done
unset _counter
unset _max

运行示例二

./example_two.sh "$(seq 1 5)"
## same output as example one

示例三(奖励)

#!/usr/bin/env bash
_arr_args=( "${@}" )
let _counter=0
let _max="${#_arr_args[@]}"
until [ "${_counter}" = "${_max}" ]; do
    echo "${_arr_args[${_counter}]}"
    let _counter=++
done
unset _counter
unset _max

运行示例三

./example_three.sh "$(seq 1 5)"
## same output as example one

新 Bash 脚本编写者须知

  • 查找内置变量/数组和替换规则;它将节省您的时间、精力,并避免不必要的管道传输到其他程序。
  • 查找shellcheck它在大多数发行版中都可用,并以来自其作者的源代码形式提供,并通过 GitHub 集成到 Code Climate 中。
  • 正如上面所回避的链接在这里使用上面显示的两种循环类型以及自动代码检查的脚本示例。然而,脚本的意图远远超出了回答上述问题的范围,因此搜索“while”和“until”以查找使用这些调用的相关函数。
  • bash != sh有相似之处,但又有所不同,我个人认为 bash 是更好的选择,因为如果给定一个 sh 脚本,那么它不太可能出错,因为 shell 会用 bash 语法做一些奇怪的事情。

答案3

您正在将字符串分配'expr $a + 1'给 a。这不太可能是您想要的。只需将单引号更改为反引号即可:

a=`expr $a + 1`

以上应该可以回答你的问题了。以下是一些额外的想法:

如果您的/bin/sh实现是 Bash,您也可以考虑使用$(...)而不是反引号。这有几个优点:它避免了单引号和反引号之间的印刷混乱,表单$(...)可以嵌套,并且每个嵌套都在其自己的引用上下文中(因此您可以执行以下操作:

variable="$(somecommand -o "$file")"

这是另一个实现:

#/bin/bash

declare -i a=0
while [[ $a -lt 5 ]]; do
   echo $a
   ((a++))
done

请注意,这sh不是一个实现。因此,为了安全地回答您的问题,我们需要知道您的意图是否包括 POSIX 可移植性,或者您是否对特定实现感兴趣,例如Bashdashtcsh等。

相关内容