循环 Bash 脚本,输出有多少用户使用某个 shell

循环 Bash 脚本,输出有多少用户使用某个 shell

因此,我坚持尝试创建一个 bash 脚本 while 循环函数,该函数从 /etc/passwd 获取输入并输出有多少用户使用 bash、nolongin、csh 和 ksh。我相信我应该使用 cat 和 cut。而且我知道用户使用的 shell 类型在第 7 个字段。

我是否正确地认为我应该为每种类型的 shell 创建一个变量,并在每次找到使用该特定 shell 的用户时增加该变量?

到目前为止,这是我拥有的代码,但由于某种原因,它只输出最后的 if 语句。

declare -i bash;
declare -i nologin;
declare -i csh;
declare -i ksh;

bash=0;
nologin=0;
csh=0;
ksh=0;
cat /etc/passwd | cut -d: -f7 $line | while read line;
do
    if [ $line == "bash" ]
            then
                    bash=bash+1;
    else  fi [ $line == "/sbin/nologin" ]
            then
                    nologin=nologin+1;
    else fi [ $line == "chs" ]
            then
                    chs=chs+1;
    else
            then
                    ksh=ksh+1;
    fi
done

更新:到目前为止,我已经更改了代码并更新了现有内容。它循环并给出 if 语句的正确部分,但我在尝试增加现有变量时遇到了麻烦。

答案1

这是我的版本:

#!/bin/bash

bash=0;
nologin=0;
csh=0;
ksh=0;

while read line;
do
    innerline=$(echo "$line"| cut -d: -f7)

    if [[ $innerline == "/bin/bash" ]]
    then
                    bash=$(echo "$bash+1"|bc);
    elif [[ $innerline == "/sbin/nologin" ]]
    then
                    nologin=&(echo "$nologin+1"|bc);
    elif [[ $innerline == "/bin/csh" ]]
    then
                    csh=$(echo "$csh+1"|bc);
    else
                    ksh=$(echo "$ksh+1"|bc);
    fi
done < /etc/passwd

echo "$bash $nologin $csh $ksh"

为了增加值,我将计算作业传递给bc小型计算器实用程序。

请让我知道这对你有没有用。

说实话,我真的不喜欢这个解决方案。While 循环是不必要的,我更喜欢 @Nat 解决方案,但是既然你明确指出了 while 循环必须存在 - 那么就在这里。

PS. 这真是个糟糕的想法:

else
                        ksh=$(echo "$ksh+1"|bc);

假设每个未知/不匹配的壳都是ksh

答案2

我不确定这是否是家庭作业,所以这可能不符合您的要求,但您实际上不需要整个脚本来执行此操作。这可以用一行代码完成。

cat /etc/passwd | cut -d ':' -f 7 | sort | uniq -c

输出结果如下

  4 /bin/bash
  6 /sbin/nologin
  4 /usr/bin/csh
 13 /usr/bin/ksh

其工作原理是uniq(1)“过滤器邻近的来自输入的匹配行”,因此使用该-c选项它将计算相邻行,这就是为什么我们需要先对行进行排序以便所有匹配的行都是相邻的。

答案3

有人认为

 cat /etc/passwd | while read line;

将放入行

 tmpfoo:x:1004:1005:utilisateur test sudo:/home/tmpfoo:/bin/bash

然后,

  cut -d: -f7 $line == "bash"

将评估为

 cut -d: -f7 tmpfoo:x:1004:1005:utilisateur test sudo:/home/tmpfoo:/bin/bash == "bash"

cut 将在 3 个文件 tmpfoo:x:1004:1005:utilisateur、test 和 sudo:/home/tmpfoo:/bin/bash 中进行搜索,这可能不是您想要的。

作为礼物,尝试一下此示例循环

cat /etc/passwd |  cut -d: -f7 | while read line;
do
    echo $line
done

答案4

我认为我应该使用catcut

这是我正在为 Unix 课程研究的东西,所以我应该创建一个 while 循环函数。

当然,记录长度可变、由换行符分隔且字段长度可变、由单个分隔符分隔的文件(如 UNIX 版本 7 密码文件)是其awk擅长的领域。因此,为了方便那些不受上述限制的人,下面是一行awk代码:

awk -F:'{x[$7]++;} END {for (k in x) print k":"x[k]}'/etc/passwd

这里要吸取的教训是:

  • UNIX 拥有专门针对其历史数据库文件格式而定制的工具。这种特殊类型的文件格式在 中处理起来轻而易举awk
  • 您不必使用cat,不管教员怎么说。☺ 有过度使用命令管道这样的事情。在while循环情况下,简单的重定向就可以了,就像 mnmnc 的回答一样。在的情况下awk,要处理的文件只是作为参数给出。
  • 这里的循环while当然是在awk程序内部。它的主要功能是按顺序读取和处理输入文件中的所有记录,这是通过循环来实现的。
  • 我是否正确地认为我应该为每种类型的 shell 创建一个变量,并在每次找到使用该特定 shell 的用户时增加该变量?
    是的,awk这里的单行代码使用了所谓的关联数组x变量。脚本的第二部分awk展示了迭代此类关联数组的内容。第一部分只是++数组中一个元素值的增量(后缀运算符),由记录的第七字段索引(可用作awk$7

    注意你也可以在 Bourne Again shell 脚本中执行关联数组并将此技术应用于受限答案的脚本。您可能只能使用循环while;但没有人限制你使用if语句

进一步阅读

相关内容