Linux 使用grep和cut筛选who的输出

Linux 使用grep和cut筛选who的输出,linux,bash,Linux,Bash,我有一个练习: 创建一个bash脚本,检查作为参数传递的用户是否正确 已连接,并且在连接时显示是否已连接。指示:使用who命令、grep筛选器和 命令切断 但我有一些麻烦来解决它 #!/bin/bash who>who.txt; then grep $1 who.txt for a in who.txt do echo "$a" done else echo "$1 isnt connected" fi 首先,我只想保留一行,我可以

我有一个练习:

创建一个bash脚本,检查作为参数传递的用户是否正确 已连接,并且在连接时显示是否已连接。指示:使用who命令、grep筛选器和 命令切断

但我有一些麻烦来解决它

#!/bin/bash
who>who.txt;
then
    grep $1 who.txt
    for a in who.txt
    do
        echo "$a"
    done
else
    echo "$1 isnt connected"
fi
首先,我只想保留一行,我可以在.txt中找到用户,然后我想在who命令中用一个循环剪切每个部分,只保留日期,但问题是我不知道如何在这里剪切,因为它用多个空格分隔


所以我真的被堵住了,我不知道该怎么做。我是bash的初学者。

如果我知道您只是想检查用户是否登录,那么这就是
users
命令的作用。如果要将其包装成一个简短的脚本,则可以执行以下操作:

#!/bin/bash

[ -z "$1" ] && {  ## validate 1 argument given on command line
    printf "error: insufficient input, usage: %s username.\n" "${0##*/}" >&2
    exit 1
}

## check if that argument is among the logged in users
if $(users | grep -q "$1" >/dev/null 2>&1) ; then
    printf " user: %s is logged in.\n" "$1"
else
    printf " user: %s is NOT logged in.\n" "$1"
fi
示例/使用

$ bash chkuser.sh dog
 user: dog is NOT logged in.

$ bash chkuser.sh david
 user: david is logged in.

cut
对于解析
who
的输出是一个相当笨拙的工具,除非您使用固定的列位置。在分隔符模式下,使用
-d'
,每个空格将生成一个单独的空字段。它不像
awk
那样,字段由一行空格分隔

who(1)
输出如下(GNU
who
没有选项将其缩减为用户名/时间):

我没有检查很长的用户名会发生什么,不管它们是否被截断,或者它们是否将行的其余部分移到另一行。使用
awk'{print$3,$4}
解析它会感觉更安全,因为不管列的确切位置如何,它仍然可以工作

但由于您需要使用
cut
,因此我们假设这些精确的列位置(从23开始到38的时间)在我们希望该脚本工作的所有系统以及所有终端宽度中都是恒定的。(
who
对于
$COLUMNS
或tty驱动程序列宽(
stty-a
输出中的
COLUMNS
字段),似乎不会改变其输出)

综上所述:

#!/bin/sh
who | grep "^$1 " | cut -c 23-38
grep命令行上的正则表达式将只在行首匹配,并且必须匹配用户名后面的空格(以避免子字符串匹配)。然后通过
cut
过滤匹配的行,以仅提取包含时间戳的列

如果cmdline arg为空,则将打印每个登录用户的登录时间。如果模式与任何内容都不匹配,则输出将为空。要显式地检测并打印其他内容,请使用
var=$(pipeline)
捕获管道输出,并测试它是否为空字符串

这将为来自同一用户的每个单独登录打印时间。您可以使用grep的count limit arg(参见手册页)在一场比赛后停止,但这可能不是最近的一次。您可以使用
sort-n | head-1
或其他方法


如果您不必在shell中编写循环,就不要这样做。最好编写一个管道,让一个人通过数据。shell本身速度很慢,但只要它不必解析您正在处理的每一行内容,这并不重要

还要注意我是如何用双引号引用
$1
的扩展的,以避免shell对其应用分词和全局扩展


有关更多shell内容,请参阅。这是一个很好的入门学习习惯用法的地方(即,当您的文件名和目录中有空格,或文件名包含
,或带有尾随空格的行,您不想咀嚼…)时,不要中断。

脚本的开头是否应该有
if
?显示
who
的输出示例会很有用。您可能需要查看“管道”功能,以便将一个命令的输出直接发送到另一个命令。例如,您可以将
who
的输出导入
grep
,将
grep
的输出导入
cut
,所有这些都在一条管道中。请注意,who.txt中的
对于who.txt的
不会循环到
who.txt
的内容上。循环运行一次,使用
a=who.txt
。有关如何解析文件,请参阅Bash常见问题解答(在我的答案中链接)。你可以用
who |而IFS=read…
,在纯bash中(除了
who
),而不是使用
grep
cut
来解决整个问题,如果你真的想这样做的话。将
grep
管道放在命令替换中,而不仅仅是
if-who | grep-q。。。;那么
?您不希望管道打印任何未重定向到/dev/null的输出,因为它将作为命令运行,而不是显示为脚本输出。可能更有用的是将输出捕获到变量中,以便他可以使用
cut
对其进行过滤,以获得登录时间。同意。将
用户的结果
放入数组等。。始终是一个选项,但不知道提问者的专业水平,我不愿意用额外的语法使解决方案过于复杂,等等--另外,这个问题现在和我回答的时候大不一样了。哦,在发帖后的前5分钟里,OP做了一些编辑吗?修订列表仅为原始->我的重新引用。我花了一段时间才找到实际想要的输出,但它就在他引用的家庭作业中。如果我没记错的话,最初的问题基本上只是我回答它时的第一句话。
#!/bin/sh
who | grep "^$1 " | cut -c 23-38