在 bash 腳本中做我的第一步。到目前為止,我已經完成了 5/7 的練習,卡在了最后兩個練習中,我找不到解決它的方法。
這是所請求練習的更好翻譯,同樣應該使用簡單的命令來解決,如 sed、echo、cat、uniq、tr、grep、wc 等:
撰寫顯示默認 shell 是您機器上可用 shell 之一的用戶數量的命令列。執行命令時,對于每個 shell,我們將得到與以下相同形式的結果:
- 0 個用戶擁有 shell / bin / sh
- 11 個用戶有 for shell/bin/bash
- 0 個用戶有 for shell /usr/bin/sh
- 0 個用戶有 for shell /usr/bin/bash
uj5u.com熱心網友回復:
這就是我如何理解您的問題,一種使用陣列的方法,包括關聯陣列。
#!/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.
uj5u.com熱心網友回復:
你在正確的軌道上。您可以使用以下腳本:
#!/bin/bash
# usual syntax to read a file line by line
# https://linuxhint.com/while_read_line_bash/
while IFS= read -r shell
do
# if our file contains commented lines, we ignore them
[[ "$shell" =~ ^[[:space:]]*# ]] && continue
count=$(grep -c ".*:$shell" /etc/passwd)
echo "- $count users have shell $shell"
done < /etc/shells
這/etc/shells是一個包含系統上所有可用登錄 shell 的檔案。
/etc/passwd在其他系統檔案,其中包含您系統上的每個用戶,以及與之相關的殼的表(格式:<username>:XXX:XXX:XXX:XXX:XXX:<shell>)
我們用grep -c ".*:$shell" /etc/passwd找到的行數/etc/passwd為此通過:<the current shell>
編輯:如果教授為您提供了一個 shell 串列,您可以將它們全部粘貼到一個檔案中(即,input.txt)并替換done < /etc/shells為done < ./input.txt
uj5u.com熱心網友回復:
假設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
uj5u.com熱心網友回復:
Unix 實用程式和 Bash 行程替換
在 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/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,無論是否有人使用它們。tac | xargs -n2如果您希望在外殼名稱之前列出數字,您甚至可以將最后一行更改為。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/314504.html
上一篇:Tcl中控制流的概念性錯誤
