在bash中打印两次的循环

时间:2018-02-08 18:46:22

标签: bash shell

我正在编写这个bash脚本,该脚本应打印出所有从未登录过的用户,并对其进行排序。我设法让所有输入工作,但是,在打印输出时遇到问题。循环如下:

    for user in $(lastlog | grep -i 'never' | awk '{print $1}'); do
            grep $user /etc/passwd | awk -F ':' '{print $1, $3}'
    done

当然,这个循环不会对输出进行排序,但是,由于我对shell和shell脚本的理解有限,它应该只是放一个'|排序'在第一个'awk'{print $ 1}'之后。我的问题是这个循环的输出打印每个用户至少两次,在某些情况下,打印四次。为什么这样,我该如何解决?

3 个答案:

答案 0 :(得分:2)

好吧,让我们尝试调试它:

for user in $(lastlog | grep -i 'never' | awk '{print $1}'); do
        echo "The user '$user' matches these lines:"
        grep $user /etc/passwd | awk -F ':' '{print $1, $3}'
        echo
done

输出:

The user 'daemon' matches these lines:
daemon 1
colord 112

The user 'bin' matches these lines:
root 0
daemon 1
bin 2
sys 3
sync 4
games 5
man 6
(...)

事实上,colord的条目确实包含daemon

colord:x:112:120:colord colour management daemon,,,:/var/lib/colord:/bin/false
                                          ^-- Here

games条目与bin匹配:

games:x:5:60:games:/usr/games:/usr/sbin/nologin
                                    ^-- Here

因此,不是在任何地方匹配用户名字符串,我们只想将它从行的开头到第一个冒号匹配:

for user in $(lastlog | grep -i 'never' | awk '{print $1}'); do
        echo "The user '$user' matches these lines:"
        grep "^$user:" /etc/passwd | awk -F ':' '{print $1, $3}'
        echo
done

现在每个条目只显示它应该的单独条目,所以你可以移除回声并继续前进。

如果您对精细和抛光感兴趣,这里有一个替代解决方案,可以跨语言设置,奇怪的用户名,网络身份验证,大型列表等高效工作:

LC_ALL=C lastlog | 
   awk -F ' ' '/Never logged in/ {printf "%s\0", $1}' |
   xargs -0 getent passwd | 
   awk -F : '{print $1,$3}' |
   sort

答案 1 :(得分:2)

试想一下名为sh的用户会发生什么。 grep sh匹配的用户数量是多少?可能所有这些,因为每个都在shell字段中使用了一些shell。

你应该考虑

awk -F ':' '$1 == "'"$user"'" {print $1, $3}' /etc/passwd

或用户的awk变量:

awk -F ':' -vuser="$user" '$1 == user {print $1, $3}' /etc/passwd

答案 2 :(得分:0)

你的grep将匹配多行,(man将匹配manuel和norman等)将它锚定到行的开头并添加一个踪迹:。

grep "^${user}:" /etc/passwd | awk -F ':' '{print $1, $3}'

更好的选择可能是忘记完全grepping / etc / passwd并使用id命令获取用户ID:

id=$(id -u "${user}" 2>/dev/null) && printf "%s %d\n" "${user}" "${id}"

如果id命令失败,则不打印任何内容,或者可以将其修改为:

id=$(id -u "${user}" 2>/dev/null)
printf "%s %s\n" "${user}" "${id:-(User not found)}"

在gnu linux中我很确定找不到找到的用户id是不可能的,因为lastlog只会报告现有用户,所以第二个例子可能毫无意义。