我希望能够用任意字符串填充数组的元素,例如可能包含 \ 和空格的字符串。我写了这个:
#!/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
while 块仅用于检查数组元素。该函数非常简单,对于不包含space
或 的参数来说,它可以很好地工作\
。否则不行。
尝试向可执行文件输入以下参数:
#!> bash [scriptname] lkl1239 343.4l 3,344 (34) "lklk lkl" lkaa\ lkc
我想看到 6 个论点:
lkl1239
343.4l
3,344
(34)
lklk lkl
lkaa lkc
相反,我被抛出:
- 对于
(
=> bash:意外标记“34”附近有语法错误 - 包含空格的字符串被解释为 x+1 字符串,其中 x 是字符串开头和结尾处不连续空格的数量。
- Bash 会忽略第一次出现
\
这是怎么做的?
答案1
你做的事情很棘手。正常的做法是避免这种情况,只将数组值作为参数传递。为了同时拥有这两个选项,你必须使用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
如果将数组值作为参数传递,则仍需要对括号进行转义,因为括号( )
是 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
和
$ 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
答案2
只需引用$@
您在函数调用中正确执行的操作即可:
array=("$@")
正如man bash
所说:
"$@"
相当于"$1" "$2" ...
答案3
特殊字符通常必须用反斜杠进行转义,如下所示:
$ array-script.sh lkl1239 343.4l 3,344 \(34\) "lklk lkl" lkaa\ lkc
6 array elements
lkaa lkc
lklk lkl
(34)
3,344
343.4l
lkl1239
shell 将括号视为元字符,因此需要进行转义。lkaa\ lkc 中的反斜杠已经转义了 lkaa 和 lkc 之间的空格,因此这两个字符串被视为一个。与cd /home/user/bin/NAME\ WITH\ SPACE
来自man bash
:
metacharacter
A character that, when unquoted, separates words. One of the following:
| & ; ( ) < > space tab
答案4
你可以尝试将下面的内容放在脚本顶部
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
和
IFS=$SAVEIFS
在脚本的底部