bash 如何改进这个脚本

bash 如何改进这个脚本

我是 shell 脚本新手,我想知道是否有比我想出的更好的解决方案:

我想检查用户是否在列表中,如果是,则脚本应使用 exit_program 函数终止:

$USER 被定义为登录系统的人

我的解决方案(有效)是:

$IGNORE_USER="USER1 USER2 USER3"

if [ ! -z "$IGNORE_USER" ]; then
for usr in $IGNORE_USER
    do
    if $USER = $usr; then
        exit_program "bye bye"    
    fi
    done
fi

答案1

该脚本的作用是不是工作。

第一行存在语法错误,因为对 的赋值IGNORE_USER不应使用 取消引用变量$。您的语句中还有另一个语法错误if。用于[ "string1" = "string2" ]比较字符串。

您的代码依赖于使用$IGNORE_USER不带引号的。这将字符串按空格分割,这就是您想要做的。在最一般的情况下,这是不是不过,您想要做什么,因为列表中的项目很可能包含应保留的空白字符。如果使用不带引号的字符串,shell 还会对字符串中的值执行文件名生成(通配符)。

当您处理单独的项目(用户名)时,最好使用数组。每当您想将单独的项目视为分离项目,不要将它们放在单个字符串中。这样做可能会导致难以区分一件物品和另一件物品。

建议:

ignore=( 'user1' 'user2' 'user3' )

for u in "${ignore[@]}"; do
    if [ "$USER" = "$u" ]; then
        exit_program 'bye bye'
    fi
done

这假设exit_program负责退出程序。如果没有,请exit在调用后添加exit_program。无需测试ignore数组是否为空,因为如果为空,循环将不会运行单次迭代。

在上面的代码中,"${ignore[@]}"(注意双引号)将扩展到用户名列表,每个用户名都单独引用并防止进一步的分词和文件名生成。

有关的:


对于不特定于 的版本bash,但可以在任何类似 POSIX 的 shell 中运行:

set -- 'user1' 'user2' 'user3'

for u do
    if [ "$USER" = "$u" ]; then
        exit_program 'bye bye'
    fi
done

这使用位置参数列表作为要忽略的用户名列表,而不是数组。

答案2

grep解决方案

使用 , 的“-w”功能grep来匹配单词。我敢说它不适用于较旧的grep实现,例如 Solaris、AIX 等。

echo $IGNORE_USER | grep -qw $USER && exit_program 'bye bye'

在线尝试一下!

bash内部解决方案

完全使用 bash,不要依赖grep.

bash不允许构造=~ regex除非你shopt -s compat31先运行。因此,通过使用=~ $(echo regex)我们可以克服这个问题。我们在这个例子中使用双引号,以便$USER扩展,这样做时我们需要转义 to \bbe \\b

[[ $IGNORE_USER =~ $(echo "\\b$USER\\b") ]] && exit_program 'bye bye'

在线尝试一下!

相关内容