基本Linux Bash脚本编写while / for

1yjd4xko  于 2022-11-02  发布在  Linux
关注(0)|答案(3)|浏览(241)

在做bash脚本的第一步。到目前为止,我做了5/7个练习,最后两个练习卡住了,我找不到解决它的方法。
这里有一个更好的翻译请求exercise,同样应该解决使用简单的命令,如sed,echo,cat,uniq,tr,grep,wc等:
编写一个命令行,显示默认shell是您计算机上可用shell之一的用户数。执行该命令时,对于每个shell,我们将得到如下形式的结果:

  • 0个用户拥有shell / bin / sh
  • 11个用户拥有shell / bin / bash
  • 0个用户拥有shell / usr / bin / sh
  • 0个用户拥有shell / usr / bin / bash

@托德
我今天早上做的,你的grep重定向输入给了我这个想法。下面是我是怎么做的:

  • count=$(echo $result I awk -F” “ '{print $1}')
  • count=$(echo $result I awk -F” “ '{print $1}')
  • shell=$(echo $result | awk -F” “'{print $2}')
  • echo $result | while read i; do
  • echo $count utilisateurs ont pour shell $shell
  • done
xa9qqrwz

xa9qqrwz1#

Unix实用程序和Bash进程替换

在Bash中,有很多方法可以做到这一点。然而,从实际的Angular 来看,你并不需要Bash本身来解决这个问题。标准的 *nix工具就可以做得很好,只要你把它们正确地连接起来。例如,如果你的输出的特定格式不是重点:

$ grep -of <(grep '^/.*$' /etc/shells) /etc/passwd | sort | uniq -c
   11 /bin/bash
    8 /bin/sh
    4 /usr/local/bin/fish

这基本上就是从/etc/shells中grep你的shell,然后grep把 * 那个 * 输出作为一个文件来读取表达式,以便与/etc/passwd进行匹配。然后它把结果输送到sort和uniq实用程序来计算出现次数。它依赖于进程替换,不是所有的shell都有或者表达相同的方式,但是你的问题被标记为Bash,所以避免Bashisms不是主要的问题。
然而,由于并非所有的shell都有Bash所做的进程替换重定向,像这样的解决方案在不同的shell之间并不是100%可移植的。通常有一种类似的方法可以做到这一点,但有时跨系统和shell的可移植性真的很重要。无论如何,这表明了grep、管道和进程替换是多么强大。
获得原始数据后,可以使用printf、awk或者sed(如果需要不同的格式)来格式化输出。但是,如果要计算shell的使用情况,则可以使用Bash或zsh来轻松完成。

更便携的替代方案

一个更复杂(但也更易于移植)的替代方法是使用xargs作为管道的核心元素。

$ grep -o '^/.*$' /etc/shells |
    xargs -I{} -L1 -- sh -c 'echo "{}"; grep -Fc "{}" /etc/passwd' |
    xargs -n2
/bin/bash 11
/bin/csh 0
/bin/ksh 0
/bin/sh 8
/bin/tcsh 0
/bin/zsh 0
/usr/local/bin/fish 4

这将找到/etc/shells中的所有shell,将它们传递给Bourne脚本(一次一个)以打印shell的路径,并让grep的固定字符串匹配器计算/etc/passwd中的出现次数,然后将输出再次通过管道传递给xargs,以一次将两行连接起来。
这种方法的主要好处是它会列出 * 所有 * shell,无论是否有人在使用它们。如果希望数字列在shell名称之前,甚至可以将最后一行改为tac | xargs -n2

bxgwgixi

bxgwgixi2#

这就是我对你的问题的理解,一种使用数组的方法,包括关联数组。


# !/usr/bin/env bash

declare -A Shell_and_Users

while IFS=: read -ra lines; do
  login_shell="${lines[-1]}"
  ((Shell_and_Users["$login_shell"]++))
done < /etc/passwd

要检查关联数组Shell_and_Users的值,请运行:

declare -p Shell_and_Users

现在循环遍历关联数组以打印所需的输出。

for i in "${!Shell_and_Users[@]}"; do
  printf -- '- %d users have shell %s\n' "${Shell_and_Users[$i]}" "$i"
done

如果不是这种情况,那么编辑问题并添加更多细节,如果文件/etc/shells应该解析/涉及,因为上面的解决方案将永远不会打印0 users

acruukt9

acruukt93#

假设可以使用awk,您可以尝试以下操作

$ cat awk.script

# !/usr/bin/env awk -f

BEGIN {
    FS=":"
} $NF=="/bin/bash" {
    count_bash++
    bash=$NF
} $NF=="/usr/bin/bash" {
    count_bash2++
    bash2=$NF
} $NF=="/bin/sh" {
    count_sh++
    sh=$NF
} $NF=="/usr/bin/sh" {
    count_sh2++
    sh2=$NF
} END {
    print count_bash " users have a shell for "bash "\n" \
          count_bash2" users have a shell for "bash2 "\n" \
          count_sh " users have a shell for "sh "\n" \
          count_sh2" users have a shell for "sh2 "\n" \
}

这将给予与预期输出类似的输出,但是,如果shell未在使用,则会得到一个没有值或路径的空输出,这可能不是理想的输出。

输出

$ awk -f awk.script /etc/passwd
24 users have a shell for /bin/bash
 users have a shell for
2 users have a shell for /bin/sh
 users have a shell for

相关问题