首页 > 解决方案 > shell脚本中的多个条件for循环

问题描述

我正在尝试遍历 macOS 上的 2 个组,如果管理员组中的用户不存在于另一个组中,则删除它们。

newadmins=$(dscl . -read Groups/newadmin GroupMembership | cut -c 18-)
adminUsers=$(dscl . -read Groups/admin GroupMembership | cut -c 18-)

for (user in $adminUsers && ! user in $newadmins)
do
        dseditgroup -o edit -d $user -t user admin
        if [ $? = 0 ]; then echo "Removed user $user from admin group"; fi
    else
        echo "Admin user $user left alone"
    fi
done

以上没有奏效。我想我将 shell 与其他语言混淆了。任何帮助,将不胜感激。谢谢!

以下脚本完全按预期工作:

NEW_ADMIN_USERS=$(dscl . -read Groups/newadmin GroupMembership | cut -d ' ' -f 2-)
ADMIN_USERS=$(dscl . -read Groups/admin GroupMembership | cut -d ' ' -f 2-)

DEFUNCT_ADMIN_USERS=$(grep -vxFf <(echo ${NEW_ADMIN_USERS} | tr ' ' '\n') <(echo ${ADMIN_USERS} | tr ' ' '\n'))

for DEFUNCT_ADMIN_USER in ${DEFUNCT_ADMIN_USERS}
do
    if dseditgroup -o edit -d ${defunct_admin_user} -t user admin
  then
    echo "Removed user ${DEFUNCT_ADMIN_USER} from admin group"
  else
    echo "Admin user ${DEFUNCT_ADMIN_USER} left alone"
  fi  
done

感谢@msbit 的所有帮助!

标签: bashloopsshellfor-loop

解决方案


我会考虑做这样的事情:

#!/usr/bin/env bash

set -eu

NEW_ADMIN_USERS=$(dscl . -read Groups/newadmin GroupMembership | cut -d ' ' -f 2-)
ADMIN_USERS=$(dscl . -read Groups/admin GroupMembership | cut -d ' ' -f 2-)

DEFUNCT_ADMIN_USERS=$(grep -vxFf <(echo ${NEW_ADMIN_USERS} | tr ' ' '\n') <(echo ${ADMIN_USERS} | tr ' ' '\n'))

for DEFUNCT_ADMIN_USER in ${DEFUNCT_ADMIN_USERS}
do
  if dseditgroup -o edit -d ${DEFUNCT_ADMIN_USER} -t user admin
  then
    echo "Removed user ${DEFUNCT_ADMIN_USER} from admin group"
  else
    echo "Admin user ${DEFUNCT_ADMIN_USER} left alone"
  fi  
done

这样做的主要目的是使用grep@Jetchisel 提出的命令和进程替换( ) 来准备变量中但不在变量<()中的管理员用户列表,然后迭代该变量。ADMIN_USERSNEW_ADMIN_USERS

这在许多方面与您的方法不同:

  • 设置errexitand选项,nounset这将导致脚本在命令的任何错误代码上退出,包括使用未设置的变量 ( set -eu)
  • 在解析( )的输出时使用将分隔符设置为空格的field参数cutdsclcut -d ' ' -f 2-
  • tr随后用( tr ' ' '\n')将用户列表分成几行
  • 将列表传递给for适当的(使用(是语法错误,因为我怀疑使用!会)
  • 直接评估返回代码,dseditgroup因为那是if正在测试的
  • fi删除第一个命令的尾随if,因为当您拥有时不需要它else(并且由于明显的浮动会导致语法错误else

请彻底测试,最好使用虚拟命令而不是dseditgroup在您 100% 满意它按预期工作之前,并考虑在开发时设置xtrace选项(set -x它将在执行所有命令时回显它们)。


推荐阅读