Linux用户名/etc/passwd列表
我想打印Linux用户名/etc/passwd列表,linux,sorting,grep,etcpasswd,Linux,Sorting,Grep,Etcpasswd,我想打印/etc/passwd中的最长和最短用户名。如果我运行下面的代码,它可以运行最短的(head-1),但不能运行(sort-n | tail-1 | awk'{print$2})。有人能帮我找出问题所在吗 #/bin/bash grep-Eo'^([^::]+'/etc/passwd| 读名字的时候 做 echo${#NAME}${NAME} 完成| 排序-n | head-1 | awk'{print$2}' 排序-n | tail-1 | awk'{print$2}' 问题在于,当您真
/etc/passwd
中的最长和最短用户名。如果我运行下面的代码,它可以运行最短的(head-1
),但不能运行(sort-n | tail-1 | awk'{print$2}
)。有人能帮我找出问题所在吗
#/bin/bash
grep-Eo'^([^::]+'/etc/passwd|
读名字的时候
做
echo${#NAME}${NAME}
完成|
排序-n | head-1 | awk'{print$2}'
排序-n | tail-1 | awk'{print$2}'
问题在于,当您真正需要一条管道时,您只有两条管道。所以你有grep |边读边做。。。完成|排序|头| awk
和排序|尾| awk
:第一个排序
有一个输入(即while
循环)-第二个排序
没有。所以脚本挂起是因为您的第二个排序没有输入:或者更确切地说,它有输入,但它是STDIN
有多种解决方法:
- 将
循环的输出保存到临时文件中,并将其用作while
命令的输入排序
- 重复你的while循环
- 用awk做头部和尾部
前两个涉及在密码文件上迭代两次,这可能没问题——取决于您最终要做什么。但是使用一个小的awk脚本,它可以通过
BEGIN
和END
块为您提供第一行和最后一行。如果您希望头部和尾部都来自同一个输入,您可能需要类似sed-e1b-e'$的东西!d'
在使用sed对数据进行排序以获得顶行和底行之后
所以你的剧本应该是:
#!/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'
问题是:
管道通过第一个sort-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
$awk-F:'
NR==1{min=max=$1}
长度($1)>长度(max){max=$1}
长度($1)
不需要显式循环、管道或多个命令。虽然您已经有了很好的答案,但您也可以使用POSIX shell来实现您的目标,而无需使用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"
使用管道/头/尾/awk或壳体本身都可以。有其他选择是好的
(注意:如果您有多个相同长度的用户,这只会选择第一个,如果您想保存所有名称,可以使用临时文件,并使用-le
和-ge
进行比较。)不知怎的,您总是有另一块宝藏。干得好,艾德。我相信这其实更容易。非常感谢埃德,不客气。是的,它更简单、更健壮(考虑到各种输入文件内容,您当前接受的解决方案将以有趣的方式失败)、更高效、更可移植,等等——也就是说,与带有一堆管道和其他工具的shell循环相比,它在各方面都更好。有关shell循环的一些(但不是全部)问题,请参阅,然后查看下一步要做什么。
$ sh cketcpw.sh
shortest ( 2): at
longest (17): systemd-bus-proxy