【问题标题】:Bash - loop through array of objects and combine themBash - 遍历对象数组并将它们组合起来
【发布时间】:2020-01-20 09:05:51
【问题描述】:

我正在尝试创建一个 for 循环来遍历数组中的所有项目,并将这些项目添加到字符串中。标签作为格式为“tag1 tag2 tag3”的单个字符串给出,并且可以使用语法为“-tag tag1 -tag -tag2 -tag tag3”的单个命令多次给出标记参数。我无法为这项工作创建一个 for 循环,而且我有点困惑我的代码出了什么问题。

TAGS="asd fgh jkl zxc bnm" # Amount of tags varies, but there is always at least one
ARRAY=($TAGS)
TAGSTOBEADDED=""
for i in "$ARRAY[@]"
do
  STRINGTOBEADDED="-tag ${ARRAY[$i]}"
  $TAGSTOBEADDED=$TAGSTOBEADDED+$STRINGTOBEADDED
done
command $TAGSTOBEADDED

【问题讨论】:

  • $ARRAY[@] 应该是${ARRAY[@]},否则会扩展到数组中被[@] 愚弄的第0 个元素

标签: arrays bash for-loop


【解决方案1】:

首先,正如@oguz ismail 所说,您的数组 sintax 是错误的。要遍历您持有的数组项,请使用:

for i in "${ARRAY[@]}"; { echo $i;}

第二个$TAGSTOBEADDED=$TAGSTOBEADDED+$STRINGTOBEADDED 这也是失败的。 变量设置如下var="$var 123",如果你想改变它,你不需要在变量名前面加上 $。回到代码。在这个例子中你甚至不需要一个数组,只需使用TAGS var(without ""):

for i in $TAGS; { TAGSTOBEADDED+="-tag $i"; }

【讨论】:

    【解决方案2】:

    首先:避免将事物列表存储在以空格分隔的字符串中(就像您目前对 TAGSTAGSTOBEADDED 所做的那样)——如果它们有任何“有趣”,就会出现很多问题字符(或者如果 IFS 被更改)。请改用数组。将它们存储为字符串然后转换无济于事;所有相同的潜在问题都适用于转换过程。

    我还建议在脚本中使用小写或混合大小写的变量名称,因为有一堆具有特殊含义的全大写名称,并且不小心将其中一个用于其他用途可能会产生奇怪的效果。所以,要定义标签数组,我就用这个:

    tags=(asd fgh jkl zxc bnm)
    

    脚本中还有许多语法错误。在这一行:

    for i in "$ARRAY[@]"
    

    ... shell 将尝试将$ARRAY 扩展为一个普通变量(不是数组),然后将“[@]”视为一些不相关的字符。每当您使用变量引用做任何不平凡的事情时,您都需要在变量引用周围使用大括号(如"${ARRAY[@]}")。顺便说一句,这个习语——包括双引号、大括号、方括号和 at 符号——是你在获取数组内容时几乎总是想要的。

    在这一行:

    STRINGTOBEADDED="-tag ${ARRAY[$i]}"
    

    $i 将扩展为数组元素之一,不是它的索引。也就是说,它会扩展为:

    STRINGTOBEADDED="-tag ${ARRAY[asd]}"
    

    ...这没有任何意义。你只是想要

    STRINGTOBEADDED="-tag $i"
    

    ...除了你也不想要那个,因为(正如我之前所说)在字符串中存储以空格分隔的事物列表是一个坏主意。但我会解决这个问题,因为修复它会涉及到下一行:

    $TAGSTOBEADDED=$TAGSTOBEADDED+$STRINGTOBEADDED
    

    这里有两个问题:您不希望分配给变量的美元符号($varname 获取变量的值;无论何时设置它,不要' t 使用$)。 + 也不需要添加字符串,您只需将它们首尾相连。好吧,您需要在两者之间添加一个空格,例如以下之一:

    TAGSTOBEADDED=$TAGSTOBEADDED" "$STRINGTOBEADDED
    TAGSTOBEADDED="$TAGSTOBEADDED $STRINGTOBEADDED"
    

    (通常,您应该在所有变量引用周围加上双引号;在普通赋值的右侧是少数几个可以安全地不加引号的地方之一,但我倾向于始终只使用双引号而不是而不是试图记住所有关于哪里安全和哪里不安全的例外情况。另外,只引用空格看起来很奇怪。)

    但是您也不想这样做,因为(再次)以空格分隔的字符串是一种不好的处理方式。使用数组。所以在循环之前,创建一个空数组而不是空字符串:

    tagstobeadded=()
    

    ...然后在循环内,用+=( ) 附加到它:

    tagstobeadded+=(-tag "$i")
    

    ...然后在最后,将它与所有适当的引号、大括号等一起使用:

    command "${tagstobeadded[@]}"
    

    因此,有了所有这些更改,我的建议如下:

    tags=(asd fgh jkl zxc bnm)
    tagstobeadded=()
    for i in "${tags[@]}"
    do
      tagstobeadded+=(-tag "$i")
    done
    command "${tagstobeadded[@]}"
    

    【讨论】:

      猜你喜欢
      • 2021-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 2021-11-09
      • 1970-01-01
      • 2017-05-28
      相关资源
      最近更新 更多