无法获得预期的结果shell数组

时间:2016-04-05 06:55:06

标签: bash ksh

#!/bin/sh
NR=0
getent passwd | while IFS=':' read USERNAME PSSWD MY_UID MYGID GECOS HOMEDIRS SHELLS
do
users[$NR]=$USERNAME
((NR++))
done
echo "${users[*]}"

如果我执行上面ksh替换sebang它可以正常工作,但是使用bash却不行。

1 个答案:

答案 0 :(得分:1)

sh bash 都会在管道后创建子shell。

换句话说,块从父shell继承变量,但修改不会影响父shell中的变量。

ksh 没有创建子shell,因此它正在运行。

在我的测试中,提供的脚本不能以纯 sh 运行。

一个简单的 sh 解决方案是直接使用 / etc / passwd

#!/bin/sh --
NR=0
users=""
while IFS=':' read USERNAME PSSWD MY_UID MYGID GECOS HOMEDIRS SHELLS ; do 
  users="${users} ${USERNAME}" 
  NR=$(expr "${NR}" + 1) 
done < /etc/passwd
printf "%s\n" ${users} 

下面有一个使用bash的解决方案(使用@pjh提示):

#!/bin/bash --
NR=0
passwdentries="$(getent passwd)"
if [ $? -ne 0 ] ; then
    exit 1
fi
while IFS=':' read USERNAME PSSWD MY_UID MYGID GECOS HOMEDIRS SHELLS ; do 
   users[$NR]=$USERNAME 
   ((NR++)) 
done <<<"${passwdentries}"
printf "%s\n" ${users[*]} 

为了说明这个子shell情况,下面的版本打印了所有用户,但是在父shell中变量的值仍未改变(使用@glennjackman提示):

#!/bin/bash --
NR=0
getent passwd | (
  while IFS=':' read USERNAME PSSWD MY_UID MYGID GECOS HOMEDIRS SHELLS ; do
    users[$NR]=$USERNAME
    ((NR++))
  done
  printf "%s\n" ${users[*]}
  )