【问题标题】:Shell Script: correct way to declare an empty arrayShell 脚本:声明空数组的正确方法
【发布时间】:2023-03-17 14:29:01
【问题描述】:

我正在尝试在 Shell 脚本中声明一个空数组,但遇到错误。

#!/bin/bash

list=$@

newlist=()

for l in $list; do

        newlist+=($l)

done

echo "new"
echo $newlist

当我执行它时,我得到test.sh: 5: test.sh: Syntax error: "(" unexpected

【问题讨论】:

  • 代码运行无误
  • 您确定使用bash 运行您的脚本吗?看起来脚本正在使用 sh 运行,在这种情况下不支持数组。
  • 此外,将$@ 分配给另一个参数会失去$@ 的好处,即保留单个命令行参数中的空格。抛弃list,直接使用for l in "$@"; do

标签: arrays bash shell


【解决方案1】:

用 bash 运行它:

bash test.sh

看到错误,看来您实际上是在用破折号运行它:

> dash test.sh
test.sh: 5: test.sh: Syntax error: "(" unexpected

只有这一次您可能使用了指向它的链接(/bin/sh -> /bin/dash)。

【讨论】:

  • 谢谢!运行bash script.sh 工作。但是......为什么即使使用#!/bin/bash 它也会在破折号上执行?我输入了export,我的 SHELL 设置为 bash。
  • 可能是因为sh。您可以使用ls -l /bin/shreadlink $(which sh) 查看它指向的位置。顺便说一句,根据您的参数声明数组变量newlist 的最快方法是newlist=("$@")。请注意,如果 args 是 "a b" "c" "d",不带引号 ($@),由于分词,它会在展开 ("a" "b" "c") 时拆分为 4 个参数,而使用 "$@" 时,值与空格保持原样。
  • #! 仅在您将其作为命令运行时才有效 - 通过使文件可执行 (chmod +x test.sh),然后只需在其前面输入不带任何 *sh 的文件名:@ 987654337@。如果您显式键入一个 shell 的名称,如 shbash 作为要运行的命令,那么这就是运行的命令;对于 shell,#! 行只是一个注释。
  • @MarkReed 是的,但我认为他的意思是他已经用./test.sh 运行了脚本,但dash 仍然是已执行的脚本
  • @konsolebox 如果是这种情况,它会在 bash 中执行,而 /bin/sh 链接到什么并不重要,因为 shebang 行中包含 /bin/bash
【解决方案2】:

如果数组为空,请执行以下操作:

NEWLIST=

您可以通过以下方式进行检查:

if [ $NEWLIST ] ; then
   # do something
fi

一个非空数组声明如下所示:

NEWLIST=('1' '2' '3')

在处理过程中填充数组:

ARRAY=("$(find . -name '*.mp3')")

希望对你有帮助

【讨论】:

  • NEWLIST 在该示例中的长度为 1。之后尝试回显${#NEWLIST[@]} 以查看此内容。
  • ofc,这很正常,但正如我的示例所示,“if”将按应有的方式工作,并且内部没有任何内容。所以真正的测试是它是否存在,而不是检查长度,在我的样本中实际上是 3。测试一下,不要对正常工作的东西投反对票
  • 一个空数组是一个长度为 0 的数组。NEWLIST 不是一个空数组,因为它的长度为 1。抱歉,您没有正确回答问题。您的 if 语句没有正确测试这一点。
  • 在您看来,长度为 1 的数组是“空的”?
  • 我说,我的样本运行良好,测试也正确,同样的测试对任何变量都运行良好。但无论如何,我接受了你的意见,虽然我会停止讨论。我还说,你是对的,你测试它的方式,会返回 1。但是在你返回长度之前,你可以用 [var] 测试。
【解决方案3】:

试试这个,看看你是用 dash 还是 bash

ls -al /bin/sh

如果显示/bin/sh -> /bin/dash,则输入:

sudo rm /bin/sh
sudo ln -s /bin/bash /bin/sh

然后再次输入:

ls -al /bin/sh*

那么必须这样说:

/bin/sh -> /bin/bash

这意味着现在sh 已正确定位到 Bash 并且您的数组可以正常工作。

【讨论】:

  • 谢谢,我遇到了类似的问题,但您的回答对我有帮助,但查询仍然存在。如果我在脚本顶部提到 #!/bin/bash,那么为什么在执行 shell 脚本时会出现破折号。我使用 ./tesh.sh 来执行脚本。任何解释都会非常有帮助。
【解决方案4】:

我发现以下语法更具可读性。

declare -a <name of array>

更多详情请见Bash Guide for Beginners: 10.2. Array variables

【讨论】:

    【解决方案5】:

    在 BASH 4+ 中,您可以使用以下语句来声明一个空数组:

    declare -a ARRAY_NAME=()
    

    然后您可以通过以下方式附加新项目 NEW_ITEM1 和 NEW_ITEM2:

    ARRAY_NAME+=(NEW_ITEM1)
    ARRAY_NAME+=(NEW_ITEM2)
    

    请注意,添加新项目时需要括号 ()。这是必需的,以便将新项目作为 Array 元素附加。如果您确实错过了 (),NEW_ITEM2 将成为附加到第一个数组元素 ARRAY_NAME[0] 的字符串。

    上面的例子将导致:

    echo ${ARRAY_NAME[@]}
    NEW_ITEM1 NEW_ITEM2
    
    echo ${ARRAY_NAME[0]}
    NEW_ITEM1
    
    echo ${ARRAY_NAME[1]}
    NEW_ITEM2
    

    接下来,如果你执行了(注意缺少的括号):

    ARRAY_NAME+=NEW_ITEM3
    

    这将导致:

    echo ${ARRAY_NAME[@]}
    NEW_ITEM1NEW_ITEM3 NEW_ITEM2
    
    echo ${ARRAY_NAME[0]}
    NEW_ITEM1NEW_ITEM3
    
    echo ${ARRAY_NAME[1]}
    NEW_ITEM2
    

    感谢@LenW 纠正我的追加操作。

    【讨论】:

    • 我还发现您可以使用ARRAY_NAME+=(NEW_ITEM1 NEW_ITEM2) 一次附加多个项目。所以你实际上只是连接两个数组。当不将任一数组指定为文字时,这也是可能的,尽管在这种情况下语法会有点笨拙:ARRAY1+=(${ARRAY2[@]})
    猜你喜欢
    • 2014-01-15
    • 1970-01-01
    • 2010-09-23
    • 2020-08-06
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 2016-08-05
    • 1970-01-01
    相关资源
    最近更新 更多