bash:用包含空格和特殊字符的元素填充数组

Cbh*_*ihe 5 bash special-characters scripts

我希望能够用任意字符串填充数组的元素,例如,可能包含 \ 和空格的字符串。我写了这个:

#!/bin/bash
function populate_array () {
    if [ "$#" -gt 0 ] ; then
        # Enter array w/ elements as argument of executable 
        array=($@)
        n=$#
    else
        # Invoke executable with no arg,, enter array element later
        read -p "Enter array elements separated by spaces: " -a array  
        n=${#array[@]} 
    fi
    printf "%d array elements \n" "$n"
} 

populate_array "$@"

while (("$n" > 0))   # while [ "$n" -gt 0 ] ALSO WORKS
do
    printf "%s \n" "${array[$n-1]}"
    n=$n-1
done
exit 0
Run Code Online (Sandbox Code Playgroud)

while 块仅用于检查数组元素。该函数非常简单,可以很好地处理包含 nospace或 的参数\。不是别的。

尝试将参数输入到可执行文件中:

#!> bash [scriptname] lkl1239 343.4l 3,344 (34) "lklk  lkl" lkaa\ lkc
Run Code Online (Sandbox Code Playgroud)

我想看到 6 个参数:

lkl1239
343.4l 
3,344
(34)
lklk  lkl
lkaa lkc
Run Code Online (Sandbox Code Playgroud)

相反,我被抛出:

  • 对于(=> bash:意外标记“34”附近的语法错误
  • 包含字符串的空格被解释为 x+1 个字符串,其中 x 是字符串开头和结尾的非连续空格的数量。
  • Bash 忽略了第一次出现之后的内容 \

这是怎么做的?

ter*_*don 3

你正在做的事情很棘手。正常的方法是避免这种情况,只是将数组值作为参数传递。为了拥有这两个选项,您必须使用eval

#!/bin/bash
function populate_array () {
    if [ "$#" -gt 0 ] ; then
        # Enter array w/ elements as argument of executable 
        # Note the quotes, they are needed
        array=("$@");
        n=$#
    else
        # Invoke executable with no arg, enter array element later
        # Read a string instead of an array and use eval to make it
        # into an array. That way, you can use tricks like escaping
        # spaces. You also need the -r option to protect the backslashes
        # so that eval will see them. 
        read -r  -p "Enter array elements separated by spaces: " string
        eval array="( $(printf '%s\n' "$string") )"
        n=${#array[@]} 
    fi
    printf "%d array elements \n" "$n"
} 

populate_array "$@"

while (("$n" > 0))   # while [ "$n" -gt 0 ] ALSO WORKS
do
    printf "%s \n" "${array[$n-1]}"
    n=$n-1
done
exit 0
Run Code Online (Sandbox Code Playgroud)

如果将数组值作为参数传递,则仍然需要转义括号,因为它们( )是 bash 的保留字符。有了这个警告,上面的脚本应该按您的预期工作:

$ foo.sh lkl1239 343.4l 3,344 \(34\) "lklk  lkl" lkaa\ lkc
6 array elements 
lkaa lkc 
lklk  lkl 
(34) 
3,344 
343.4l 
lkl1239 
Run Code Online (Sandbox Code Playgroud)

$ foo.sh
Enter array elements separated by spaces:  lkl1239 343.4l 3,344 \(34\) "lklk  lkl" lkaa\ lkc 
6 array elements 
lkaa lkc 
lklk  lkl 
(34) 
3,344 
343.4l 
lkl1239 
Run Code Online (Sandbox Code Playgroud)