簡體   English   中英

Linux用戶名/ etc / passwd清單

[英]Linux usernames /etc/passwd listing

我想打印在/etc/passwd找到的最長和最短的用戶名。 如果我運行下面的代碼,它在最短的( head -1 )下可以正常工作,但不能在( sort -n |tail -1 | awk '{print $2} )下運行。 誰能幫助我找出問題所在?

#!/bin/bash

grep -Eo '^([^:]+)' /etc/passwd | 
while read NAME
do
  echo ${#NAME} ${NAME}
done |
sort -n |head -1 | awk '{print $2}' 
sort -n |tail -1 | awk '{print $2}'

這里的問題是:

管道以第一個-n | head -1 |結尾 awk'{print $ 2}'命令。 因此,通過管道提供對第一命令的輸入,並獲得輸出。

對於第二個命令,沒有輸入。 因此,它等待來自鍵盤的STDIN的輸入,您可以通過鍵盤輸入該輸入,然后按ctrl + D獲得輸出。

請運行以下代碼以獲得所需的輸出:

#!/bin/bash

    grep -Eo '^([^:]+)' /etc/passwd | 
    while read NAME
    do
      echo ${#NAME} ${NAME}
    done |
    sort -n |head -1 | awk '{print $2}' 

    grep -Eo '^([^:]+)' /etc/passwd | 
    while read NAME
    do
      echo ${#NAME} ${NAME}
    done |
    sort -n |tail -1 | awk '{print $2}

'

所有你需要的是:

$ awk -F: '
    NR==1 { min=max=$1 }
    length($1) > length(max) { max=$1 }
    length($1) < length(min) { min=$1 }
    END { print min ORS max }
' /etc/passwd

不需要顯式的循環或管道或多個命令。

問題在於,當您真正需要一個管道時,您只有兩個管道。 所以你有grep | while read do ... done | sort | head | awk grep | while read do ... done | sort | head | awk grep | while read do ... done | sort | head | awksort | tail | awk sort | tail | awk sort | tail | awk :第一sort具有輸入(即, while循環) -第二sort沒有。 所以該腳本正在掛起,因為第二種排序沒有輸入:或者更確切地說,它是STDIN。

有多種解決方法:

  • while循環的輸出保存到一個臨時文件中,並用作兩個sort命令的輸入
  • 重復你的while循環
  • 用awk做頭和尾

前兩個涉及到兩次遍歷密碼文件,這可能沒問題-取決於您最終想要做什么。 但是使用小的awk腳本,這可以通過BEGINEND塊為您提供第一行和最后一行。

盡管您已經有了很好的答案,但是您也可以使用POSIX Shell來實現您的目標,而無需使用它本身提供的參數擴展字符串長度就完全不需要任何管道(請參閱: POSIX shell規范 )。 例如,您可以執行以下操作:

#!/bin/sh

sl=32;ll=0;sn=;ln=;         ## short len, long len, short name, long name
while read -r line; do      ## read each line
    u=${line%%:*}           ## get user
    len=${#u}               ## get length
    [ "$len" -lt "$sl" ] && { sl="$len"; sn="$u"; } ## if shorter, save len, name
    [ "$len" -gt "$ll" ] && { ll="$len"; ln="$u"; } ## if longer, save len, name
done </etc/passwd
printf "shortest (%2d): %s\nlongest  (%2d): %s\n" $sl "$sn" $ll "$ln"

使用/輸出示例

$ sh cketcpw.sh
shortest ( 2): at
longest  (17): systemd-bus-proxy

使用管子/頭部/尾部/木蠟或外殼本身都可以。 有其他選擇是很好的。

(注意:如果您有多個相同長度的用戶,則只選擇第一個用戶,如果要保存所有名稱並使用-le-ge進行比較,則可以使用臨時文件。)

如果希望頭和尾都來自同一輸入,則在對數據進行排序以使用sed獲得頂行和底行后,可能需要類似sed -e 1b -e '$!d'類的東西。

因此,您的腳本將是:

#!/bin/bash
grep -Eo '^([^:]+)' /etc/passwd | 
while read NAME
do
  echo ${#NAME} ${NAME}
done |
sort -n |  sed -e 1b -e '$!d'

或者,一種較短的方法:

cut -d":" -f1 /etc/passwd | awk '{ print length, $0 }' | sort -n | cut -d" " -f2- | sed -e 1b -e '$!d'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM