正在进行bash脚本编写的第一步。到目前为止,我做了5/7个练习,最后两个卡住了,我找不到解决它的方法。
这是对请求练习的更好的翻译,同样应该使用简单的命令,如sed, echo, cat, uniq, tr, grep, wc等来解决:
编写命令行,显示其默认shell是您机器上可用shell之一的用户数量。当执行该命令时,对于每个shell,我们将得到与以下相同形式的结果:
- 0 users has for shell/bin/sh
- 11个用户有shell/bin/bash
- 0用户有shell/usr/bin/sh
- 0用户有shell/usr/bin/bash
@Todd
我今天早上做的,你的grep重定向输入给了我这个想法。我是这样做的:
result=$(grep -of <(echo $SHELL) /etc/passwd | uniq -c)
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
Unix Utilities and Bash Process Substitution
在Bash中,有很多方法可以做到这一点。然而,从实际的角度来看,您并不需要Bash本身来解决这个问题。标准的*nix工具会做得很好,只要你正确地连接它们。例如,如果输出的特定格式不是重点:$ grep -of <(grep '^/.*$' /etc/shells) /etc/passwd | sort | uniq -c
11 /bin/bash
8 /bin/sh
4 /usr/local/bin/fish
这基本上是从/etc/shell中grep shell,然后grep将输出作为一个文件来读取表达式以匹配/etc/passwd然后,它将结果输送到sort和uniq实用程序,以计算出现次数。它依赖于进程替换,不是所有shell都具有或表达相同的方式,但是您的问题被标记为Bash,因此避免Bashisms不是主要问题。
然而,由于并非所有shell都具有Bash所具有的进程替换重定向,因此像这样的解决方案并不是100%可移植到不同的shell。通常有一种类似的方法可以做到这一点,但有时跨系统和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/shell中的所有shell,将它们一次一个地传递给Bourne脚本,以打印shell的路径,并让grep的固定字符串匹配器计算/etc/passwd中的出现次数,然后将输出再次管道到xargs,以每次连接两行。
这种方法的主要好处是它将列出所有shell,无论是否有人正在使用它们。如果您希望将数字列在shell名称之前,甚至可以将最后一行更改为tac | xargs -n2
。
这就是我如何理解你的问题,使用数组的一种方法,包括关联数组。
#!/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 %sn' "${Shell_and_Users[$i]}" "$i"
done
如果不是这样,那么编辑问题并添加更多的细节,如果文件/etc/shells
应该是解析/涉及,因为上面的解决方案永远不会打印0 users
。
假设可以使用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