简体   繁体   中英

bash script with grep command understanding

I posted earlier with something similar to this. I am trying to check if a user is online with the command $ ./user mburkhar which prints out mburkhar is logged on . My program works correctly but if I just type $ ./user mb is also states mb is logged on . What I have is fine, but is there a way to match what the user typed in exactly instead of slightly matching the first 2 characters..?

Here is my program so you can see what I did:

# 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

To complement the accepted answer :

-w works well and is widely supported (GNU Grep, BSD Grep), but it is not POSIX-compliant .

In your case, given that your output lines contain just a username each and nothing else, using -x - to match entire lines - would make sense too (and it is POSIX-compliant).
Also, since you're searching for a literal username, it's good practice to use grep 's -F option to indicate just that.

Using [ $(...) ] (or [ `...` ] ) to test for nonempty output from a command is somewhat fragile and inefficient; it's better and simpler to:

  • use commands directly
  • base the test on the exit code
  • and suppress stdout output, if needed

    • grep 's -q option not only suppresses stdout, but also makes the search potentially more efficient by terminating once the first match is found (with exit code 0 to indicate success):

       if who | cut -d' ' -f1 | grep -Fxq "$1"; then # ... 

Similarly, [ -z $1 ] is fragile in that would break if an argument with embedded whitespace is passed - not likely in this case, but it's better to get in the habit of using [[ -z $1 ]] (or, if you must remain POSIX-compliant, [ -z "$1" ] ).
Outside of [[ ... ]] , it makes sense to habitually double-quote variable references, such as the $1 in the grep command.

If we put it all together:

# 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

You can use grep's -w ( --word-regexp ) option to match only entire words. Replacing grep $1 with grep -w $1 in your script should fix it.

Specify the start and end of string anchors like this:

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

I also added the uniq to remove duplicate matches, in case an user got more than one tty, or [ will exit with: [: too many arguments

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM