shell 只有第一个值被追加到数组中

rsl1atfo  于 2023-06-24  发布在  Shell
关注(0)|答案(1)|浏览(182)

我在bash脚本中有这段代码。它会询问用户,我们生成的文件是否必须发送到standardTo(文件通常发送到的电子邮件),或者用户在这种情况下是否希望发送到不同的邮件。如果是,电子邮件收件人=标准收件人。如果不是,它就不使用standardTo,它会询问邮件,检查这些是否是实际的邮件,然后将它们添加到emailsTo。现在的问题是只有第一个值被追加到数组中。
在类似的主题中找到的这样做的语法总是相同的,对我来说看起来很清楚:array+=(new value).这就是我正在做的。
我还读到了这个:Unable to add element to array in bash,并认为可能我的第二个'case $yn'正在创建'subshell行为',但我真的不明白这将如何工作,以及如何确保这种行为不会发生。
我如何确保第二个,第三个...值是否也会被追加到数组中?

#!/bin/bash
standardTo=("blabla@hotmail.com" "blabloe@hotmail.com")

while true; do
    echo standard users are: "${standardTo[@]}"
    read -p "Do you wish to send to standard users ? " yn
    case $yn in
        [Yy]* ) emailsTo=${standardTo[*]}
            break;;
        [Nn]* )
            regex="^[a-zA-Z0-9\._-]+\@[a-zA-Z0-9._-]+\.[a-zA-Z]+\$"
            addmails=
            #declare –a
            emailsTo=()
            while [[ ! $addmails ]]; do
                #ask user for input
                read -p "Enter email : " email
                if [[ $email =~ $regex ]]; then
                    echo "$email is valid"
                    emailsTo+=("$email")
                    read -p "Do you wish to add another mail ? " yn
                    case $yn in
                        [Yy]* ) addmails=;;
                        [Nn]* ) addmails=false;;
                    esac
                else
                    echo "$email is invalid"
                    addmails=
                fi
            done
            break;;
        * ) echo "Please answer yes or no.";;
    esac
done

echo "loop printing all values in emailsto:"

for mail in $emailsTo
do
echo $mail
done

#setup mailstring to --> this does work 
mailtostring=""
for mail in $emailsTo
do 
    mailtostring="$mail, $mailtostring"
done

程序截图:

2ledvvac

2ledvvac1#

首先,感谢您提供足够的上下文来回答这个问题!但我怀疑如果你寻找smallest, self-contained, complete example,你自己会找到答案,它会是这样的:

$ a=(one two three)  # Initialize an array.
$ echo "$a"          # "$a" expands to the first element only.
one
$ echo "${a[@]}"     # This expands to all elements.
one two three

由此,您将在示例代码中找到问题:

for mail in $emailsTo   # Should be "${emailsTo[@]}".
do
echo $mail
done

#setup mailstring to --> this does work 
mailtostring=""
for mail in $emailsTo    # Should be "${emailsTo[@]}".
do 
    mailtostring="$mail, $mailtostring"
done

第二个问题是emailsTo在这里被声明为一个简单变量:

case $yn in
        [Yy]* ) emailsTo=${standardTo[*]}

但它在这里被当作数组变量:

emailsTo+=("$email")

一般来说,最佳做法是:
1.在变量展开式中使用双引号和大括号,除非有不这样做的理由。这样就避免了展开时的问题,如
x="a ${var}iable expansion"
1.将包含单个项的变量视为数组。
1.如果您希望将每个项目视为单个单词,即使它包含空格,也可以将数组变量扩展为"${a[@]}"而不是${a[*]}
1.展开变量时,使用$IFS更改元素之间的分隔符。
把这些放在一起:

$ emailsTo=("${standardTo[@]}")  # Create an array.
$ emailsTo+=("${email}")         # Add an element.

$ echo "${emailsTo[@]}"
me@here you@there them@anywhere  # Example output.

最后,如果你想要一个逗号分隔的字符串,你可以将$IFS设置为逗号,用"${emailsTo[*]}"(带引号,用*展开)展开数组,然后重置$IFS

$ ifs="$IFS"; IFS=","; echo "${emailsTo[*]}"; IFS="${ifs}"
me@here,you@there,them@anywhere

相关问题