我有这个练习:
创建一个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的初学者。
答案 0 :(得分:2)
如果我理解你只是想检查用户是否登录,那么这就是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.
答案 1 :(得分:0)
cut
是解析who
输出的相当尴尬的工具。在分隔符模式下,使用-d ' '
,每个空格都会生成一个单独的空字段。它不像awk
,其中字段由一系列空格分隔。
who(1)
输出看起来像这样(并且GNU who
无法将其缩减为只是用户名/时间):
$ who
peter tty1 2015-11-13 18:53
john pts/13 2015-11-12 08:44 (10.0.0.1)
john pts/14 2015-11-12 08:44 (10.0.0.1)
john pts/15 2015-11-12 08:44 (10.0.0.1)
john pts/16 2015-11-12 08:44 (10.0.0.1)
peter pts/9 2015-11-14 16:09 (:0)
我没有检查很长的用户名会发生什么,他们是否会被截断,或者他们是否会将剩下的线路移过来。使用awk '{print $3, $4}
解析它会感觉更安全,因为无论列位置如何,它仍然可以正常工作。
但是由于你需要使用cut
,我们假设那些确切的列位置(时间从23开始,一直运行到38)在我们希望这个脚本工作的所有系统中是恒定的,并且所有终端宽度。 (who
似乎不会改变$COLUMNS
或tty-driver列宽(columns
输出中的stty -a
字段)的输出。)
把所有这些放在一起:
#!/bin/sh
who | grep "^$1 " | cut -c 23-38
grep命令行上的正则表达式只会在行的开头匹配,并且必须匹配用户名后面的空格(以避免子字符串匹配)。然后,匹配的那些行将通过cut
进行过滤,以仅提取包含时间戳的列。
使用空的cmdline arg,将打印每个登录用户的登录时间。如果模式不匹配任何内容,则输出将为空。要显式检测并打印其他内容,请使用var=$(pipeline)
捕获管道输出,并测试它是否为空字符串。
这将为同一用户的每次单独登录打印时间。您可以使用grep的计数限制arg(参见手册页)在一次匹配后停止,但可能不是最近的时间。您可以使用sort -n | head -1
或其他内容。
如果您不必在shell中编写循环,请不要这样做。编写一个通过数据传递的管道要好得多。 shell本身很慢,但只要它不必解析你所处理的每一行,那都无关紧要。
另请注意我是如何用双引号引用$1
的扩展,以避免shell对其应用单词拆分和glob扩展。
有关更多shell内容,请参阅the Wooledge Bash FAQ and guide。这是一个开始学习不吸吮的习语的好地方(即当你的文件名和目录中包含空格,或者包含?
的文件名或行时,不要中断带有你想要不用的尾随空格......)。