2009-12-01 2 views
2

Я хотел бы изменить значение массива и был бы признателен за любую помощь.Bash: Как обрезать массив?

я получил массив как это:

users=(root isometric akau) 

(Это на самом деле список текущих пользователей), что я хотел бы быть в состоянии проверить, если пользователь существует, и если они этого не делают, то в удалите человека из массива. Я пробовал экспериментировать с этим, поставив его в цикле и его оценки:

for i in ${users[@]}; do 
    eval "users=($([ -z $(grep \"^\$i\" /etc/shadow) ] && sed \"s/\$i//g\"))" 
done 

echo $users 

Я думал об игре с этим некоторые больше, но я думал, что я мог бы получать слишком сложно (я не уверен, что я могу поместите команду в массив). У кого-нибудь есть идея, как это сделать?

Edit:

Как я вошел в массив переменного отключенный номер:

cnt=0 
for i in ${users[@]}; do 
    [ -z "$(grep "^$i" /etc/shadow)" ] && unset users[cnt] || ((cnt++)) 
done 

Edit2:

На самом деле Деннис является еще лучше.

ответ

5

вас может не понадобиться цикл for. Попробуйте это:

users=(root isometric akau) 
list="${users[@]/%/|}"  # convert array to list, add pipe char after each user 
# strip the spaces from the list and look for usernames between the beg. of the line 
# and the end of the word, make an array out of the result 
users=($(grep -Eo "^(${list// })\>" /etc/shadow)) 

grep, разгадали, будет выглядеть следующим образом:

grep -Eo "^(root|isometric|akau|)\>" /etc/shadow 
+0

Очень умный. Я бы дал ему плюс 2 для изобретательности, если это вообще возможно. Спасибо. –

+0

Чем больше я смотрю на это, это действительно хорошо. Вау –

0

Если вы хотите удалить jane из users:

users=(john joe mary jane liz root foobar) 

for ((i = 0; i < ${#users[@]}; ++i)); do 
    [[ ${users[i]} == jane ]] && break 
done 

users=(${users[@]:0:i} ${users[@]:i+1}) 

echo "${users[@]}" #=> john joe mary liz root foobar 

Общий принцип заключается в том, что не существует срез массива в Баш (очевидно); вам нужно воссоздать массив без исключенного элемента (ов).

Это говорит о том, что существует множество способов сделать то, что вы ищете в цикле for (in).

3

Так что если у вас есть ...

$ users=(root isometric akau) 
$ echo ${users[*]} 
root isometric akau 

Все, что вам нужно сделать, это, скажем:

$ unset users[1] 

А потом ...

$ echo ${users[*]} 
root akau 
$ 
+0

Ха-ха, хорошо. Намного лучше. Спасибо DR. Для справки я расскажу, как узнать номер значения массива в исходном сообщении. –

0
users=(root nobody akau) 
declare -a shadowusers 
declare -a notinshadow 
i=0 
while IFS=":" read -r user b c d e f g h 
do 
    shadowusers[$i]=$user 
    i=$((i+1)) 
done < "/etc/shadow" 
for u in ${users[@]} 
do 
    found=0 
    for s in ${shadowusers[@]} 
    do 
      case "$u" in 
       "$s") found=1;; 
      esac 
    done 
    [ "$found" -eq 0 ] && notinshadow[$j]=$u 
    j=$((j+1)) 
done 
echo ${notinshadow[@]} 
+0

+1 для творчества. Никогда не думал перенаправить на цикл while до ... ха. –

Смежные вопросы