【求助】把整个数组作为参数传递给函数时,数组的元素内容有空格,怎么处理?

sh/bash/dash/ksh/zsh等Shell脚本
回复
wrj20080607
帖子: 12
注册时间: 2011-12-16 21:56
送出感谢: 4 次
接收感谢: 1 次

【求助】把整个数组作为参数传递给函数时,数组的元素内容有空格,怎么处理?

#1

帖子 wrj20080607 » 2021-05-12 0:09

简单的代码如下:

代码: 全选

#!/bin/bash
a[0]='a b'
a[1]='c d'
a[2]='e f'

##define function
function1(){
  n=0
  for line in $1;
  do
    let n++
  done
  echo "function1 is $n"
}

##main1
function1 "${a[*]}"

##loop1
n=0
for line in "${a[@]}";
do
  let n++
done
echo "loop1 is $n"
运行后,function1 和loop1 的结果截然不同:

代码: 全选

ubuntu@ubuntu:~$ ./arry_function.sh 
function1 is 6
loop1 is 3
很显然,数组a的每一个元素都有空格,在函数function1里面用for循环遍历数组a时,把数组a识别成6个元素;
不在函数里面时,loop1的for循环遍历数组a,识别正确,数组a有3个元素,请问有谁知道这种情况怎么处理吗?谢谢^_^
头像
jiandan23
帖子: 58
注册时间: 2010-12-17 22:31
系统: Mint 19.2
送出感谢: 5 次
接收感谢: 1 次

Re: 【求助】把整个数组作为参数传递给函数时,数组的元素内容有空格,怎么处理?

#2

帖子 jiandan23 » 2021-05-12 10:40

a[0]='a b'
a[1]='c d'
a[2]='e f'

##define function
function1(){
n=0
for line in "$@";
do
let n++
done
echo "function1 is $n"
}

function1 "${a[@]}"
这些用户感谢了作者 jiandan23 于这个帖子:
wrj20080607 (2021-05-12 15:35)
评价: 3.7%
wrj20080607
帖子: 12
注册时间: 2011-12-16 21:56
送出感谢: 4 次
接收感谢: 1 次

Re: 【求助】把整个数组作为参数传递给函数时,数组的元素内容有空格,怎么处理?

#3

帖子 wrj20080607 » 2021-05-12 15:45

jiandan23 写了:
2021-05-12 10:40
a[0]='a b'
a[1]='c d'
a[2]='e f'

##define function
function1(){
n=0
for line in "$@";
do
let n++
done
echo "function1 is $n"
}

function1 "${a[@]}"
:Haha

非常感谢这个方法很好,论坛果然高手如云啦^_^。
想借楼再问问,如果函数function1 接收几个不同的参数,有几个数组(数组元素都有空格),有普通变量。
比如这样 function1 "${a[@]}" "${b[@]}" $c 这个时候还有办法处理吗?
wrj20080607
帖子: 12
注册时间: 2011-12-16 21:56
送出感谢: 4 次
接收感谢: 1 次

Re: 【求助】把整个数组作为参数传递给函数时,数组的元素内容有空格,怎么处理?

#4

帖子 wrj20080607 » 2021-05-12 18:11

wrj20080607 写了:
2021-05-12 15:45
jiandan23 写了:
2021-05-12 10:40
a[0]='a b'
a[1]='c d'
a[2]='e f'

##define function
function1(){
n=0
for line in "$@";
do
let n++
done
echo "function1 is $n"
}

function1 "${a[@]}"
:Haha

非常感谢这个方法很好,论坛果然高手如云啦^_^。
想借楼再问问,如果函数function1 接收几个不同的参数,有几个数组(数组元素都有空格),有普通变量。
比如这样 function1 "${a[@]}" "${b[@]}" $c 这个时候还有办法处理吗?

根据前面的 jiandan23 给出的思路,我想了一个方法,终于实现了多个数组(元素有空格)作为参数传入函数中:就是把数组a 和数组b 的各自的长度先计算出来,再作为两个参数一起传入函数中,这样就可以在函数中正确读取每一个数组了。
这个方法有点麻烦,如果哪位知道更简单的方法,可以告诉我一下啊,再次感谢各位^_^

顺便贴一下我写的代码,给有需要的人:

代码: 全选

#!/bin/bash
a=('a a' 'b b' 'c c')
b=('d d' 'e e' 'f f')
c='ccc'

##define function
function1(){
  n=0
  sum1=$1
  sum2=$2
  for line in "$@";
  do
    if [ $n -ge 2 ] && [  $n -lt $[sum1+2] ];then
      arry1[n-2]=$line
    elif [ $n -ge $[sum1+2] ] && [  $n -lt $[sum1+2+sum2] ];then
      arry2[n-2-sum1]=$line
    fi
    let n++
  done
  echo "The {a} is :  ${arry1[@]}"
  echo "The {b} is :  ${arry2[@]}"
}

##main
sum1=${#a[@]}
sum2=${#b[@]}
function1 $sum1 $sum2 "${a[@]}" "${b[@]}" $c 
执行结果为

代码: 全选

ubuntu@ubuntu:~$ ./arry_function.sh 
The {a} is :  a a b b c c
The {b} is :  d d e e f f
wrj20080607
帖子: 12
注册时间: 2011-12-16 21:56
送出感谢: 4 次
接收感谢: 1 次

Re: 【求助】把整个数组作为参数传递给函数时,数组的元素内容有空格,怎么处理?

#5

帖子 wrj20080607 » 2021-05-12 18:26

:em51 :em51 再次感谢 jiandan23 解决了我的疑惑 ,通过这个例子,我也大概明白了"${a[@]}"和"${a[*]}"传入函数的区别,类似于"$@"和"$*"
头像
astolia
论坛版主
帖子: 5173
注册时间: 2008-09-18 13:11
送出感谢: 1 次
接收感谢: 875 次

Re: 【求助】把整个数组作为参数传递给函数时,数组的元素内容有空格,怎么处理?

#6

帖子 astolia » 2021-05-12 21:34

wrj20080607 写了:
2021-05-12 18:11
根据前面的 jiandan23 给出的思路,我想了一个方法,终于实现了多个数组(元素有空格)作为参数传入函数中:就是把数组a 和数组b 的各自的长度先计算出来,再作为两个参数一起传入函数中,这样就可以在函数中正确读取每一个数组了。
这个方法有点麻烦,如果哪位知道更简单的方法,可以告诉我一下啊,再次感谢各位^_^
可以只传入数组名,然后用eval把数组的内容复制给另外的变量

代码: 全选

a=("1 1" "2 2" "3 3")
b=(a b c d)
f() {
  eval 'p1=("${'$1'[@]}")';
  eval 'p2=("${'$2'[@]}")';
  echo "1st array $1=${p1[@]}, size=${#p1[@]}";
  echo "2nd array $2=${p2[@]}, size=${#p2[@]}";
}

f a b
f b a
这些用户感谢了作者 astolia 于这个帖子:
wrj20080607 (2021-05-12 23:02)
评价: 3.7%
wrj20080607
帖子: 12
注册时间: 2011-12-16 21:56
送出感谢: 4 次
接收感谢: 1 次

Re: 【求助】把整个数组作为参数传递给函数时,数组的元素内容有空格,怎么处理?

#7

帖子 wrj20080607 » 2021-05-12 22:58

astolia 写了:
2021-05-12 21:34
wrj20080607 写了:
2021-05-12 18:11
根据前面的 jiandan23 给出的思路,我想了一个方法,终于实现了多个数组(元素有空格)作为参数传入函数中:就是把数组a 和数组b 的各自的长度先计算出来,再作为两个参数一起传入函数中,这样就可以在函数中正确读取每一个数组了。
这个方法有点麻烦,如果哪位知道更简单的方法,可以告诉我一下啊,再次感谢各位^_^
可以只传入数组名,然后用eval把数组的内容复制给另外的变量

代码: 全选

a=("1 1" "2 2" "3 3")
b=(a b c d)
f() {
  eval 'p1=("${'$1'[@]}")';
  eval 'p2=("${'$2'[@]}")';
  echo "1st array $1=${p1[@]}, size=${#p1[@]}";
  echo "2nd array $2=${p2[@]}, size=${#p2[@]}";
}

f a b
f b a
:em56 :em56 ,非常感谢astolia,版主给出的代码果然简洁,一行代码就传递了整个数组。我在上楼还写了个繁琐的循环呢 :Grimace
赶紧在terminal里面查询自己不懂的地方

代码: 全选

eval --help
eval: eval [参数 ...]
    将参数作为 shell 命令执行。
    
    将 ARGs 合成一个字符串,用结果作为 shell 的输入,
    并且执行得到的命令。
    
    退出状态:
    以命令的状态退出,或者在命令为空的情况下返回成功。
从上面的解释看,eval是将那一行参数合成了字符串,用结果作为shell命令执行了一遍

代码: 全选

  eval 'p1=("${'$1'[@]}")';
上面这行代码里面,看懂了 $1=a ,但是外面那个小括号()不知道是其什么作用的
头像
astolia
论坛版主
帖子: 5173
注册时间: 2008-09-18 13:11
送出感谢: 1 次
接收感谢: 875 次

Re: 【求助】把整个数组作为参数传递给函数时,数组的元素内容有空格,怎么处理?

#8

帖子 astolia » 2021-05-12 23:01

小括号表示是在定义数组,这句话就是在执行p1=("${a[@]}"),然后把"${a[@]}"展开就成了p1=("1 1" "2 2" "3 3")这样

另外也可以用间接引用/双重引用来代替eval,不过这样的话传入方式也要换种写法。

代码: 全选

a=("1 1" "2 2" "3 3")
b=(a b c d)
f() {
  p1=("${!1}");
  p2=("${!2}");
  echo "1st array $1=${p1[@]}, size=${#p1[@]}";
  echo "2nd array $2=${p2[@]}, size=${#p2[@]}";
}

f a[@] b[@]
f b[@] a[@]
这些用户感谢了作者 astolia 于这个帖子:
wrj20080607 (2021-05-12 23:09)
评价: 3.7%
wrj20080607
帖子: 12
注册时间: 2011-12-16 21:56
送出感谢: 4 次
接收感谢: 1 次

Re: 【求助】把整个数组作为参数传递给函数时,数组的元素内容有空格,怎么处理?

#9

帖子 wrj20080607 » 2021-05-12 23:18

astolia 写了:
2021-05-12 23:01
小括号表示是在定义数组,这句话就是在执行p1=("${a[@]}"),然后把"${a[@]}"展开就成了p1=("1 1" "2 2" "3 3")这样

另外也可以用间接引用/双重引用的来代替eval,不过这样的话传入方式也要换种写法。

代码: 全选

a=("1 1" "2 2" "3 3")
b=(a b c d)
f() {
  p1=("${!1}");
  p2=("${!2}");
  echo "1st array $1=${p1[@]}, size=${#p1[@]}";
  echo "2nd array $2=${p2[@]}, size=${#p2[@]}";
}

f a[@] b[@]
f b[@] a[@]
:em56 :em56 :em56 再次感谢版主astolia
原来如此,终于弄明白了那个小括号的作用了,eval的用法也很强大^_^
后面这个间接引用的方法更加简洁,直接 p1=("${!1}") ; 就行了
shell 编程果然博大精深 :Haha
回复

回到 “Shell脚本”