我之前发布过类似的内容。我正在尝试使用命令$ ./user mburkhar
检查用户是否在线,该命令打印出mburkhar is logged on
。我的程序工作正常,但如果我只输入$ ./user mb
,则状态为mb is logged on
。我有什么不错,但有没有办法匹配用户输入的内容而不是略微匹配前2个字符..?
这是我的程序,所以你可以看到我做了什么:
# Check if a user is logged on
if [ -z $1 ] ; then
read user
else
user=$1
fi
if [ `who | cut -d" " -f1 | grep $1` ] ; then
echo "$1 is logged on"
else
echo "$1 is either not valid or logged on"
fi
答案 0 :(得分:1)
-w
效果很好,受到广泛支持(GNU Grep,BSD Grep),但it is not POSIX-compliant。
在您的情况下,假设您的输出行包含只是一个用户名,而不是其他任何内容,使用-x
- 来匹配整个行 - 会有意义也是( POSIX兼容)
此外,由于您正在搜索文字用户名,因此使用grep
-F
选项来表示该用户名是一种很好的做法
使用[ $(...) ]
(或[ `...` ]
)来测试命令的非空输出有点脆弱且效率低下;它更好,更简单:
并根据需要抑制标准输出
grep
' -q
选项不仅可以抑制stdout,还可以在找到第一个匹配后终止,从而提高搜索效率(使用退出代码0
表示成功):
if who | cut -d' ' -f1 | grep -Fxq "$1"; then # ...
同样地,[ -z $1 ]
是脆弱的,如果传递带有嵌入空格的参数会破坏 - 在这个的情况下不太可能,但它better to get in the habit of using [[ -z $1 ]]
(或者,如果您必须保持POSIX兼容,[ -z "$1" ]
)
在[[ ... ]]
之外,习惯性地引用变量引用是有意义的,例如$1
命令中的grep
。
如果我们把它们放在一起:
# Check if a user is logged on
if [[ -z $1 ]]; then
read user
else
user=$1
fi
if who | cut -d' ' -f1 | grep -Fxq "$1"; then
echo "$1 is logged on"
else
echo "$1 is either not valid or logged on"
fi
答案 1 :(得分:0)
您可以使用grep的-w
(--word-regexp
)选项仅匹配整个单词。在脚本中用grep $1
替换grep -w $1
应修复它。
答案 2 :(得分:0)
指定字符串锚点的开头和结尾,如下所示:
if [ -z $1 ] ; then
read user
else
user="^$1$"
fi
if [ $(who | cut -d" " -f1 | grep $user | uniq ) ] ; then
echo "$1 is logged on"
else
echo "$1 is either not valid or logged on"
fi
我还添加了uniq
以删除重复的匹配项,以防用户获得多个tty,或[
将退出:[: too many arguments