1
#!/bin/bash
# This tells you that the script must be run by root.
if [ "$(id -u)" != "0" ];
  then
echo "This script must be run as root!" 1>&2
exit 1
fi

userexists=0
while [ $userexists -eq 0 ]
do
# This asks for the user's input for a username.
  echo -n "Enter a username: "
  read username

  x="$username:x:"
# This if block checks if the username exists.
  grep -i $x /etc/passwd > /dev/null
  if [ $? -eq 0 ]
    then
      userexists=1
    else
      echo "That user does not exist!"
  fi
done
# This is the heading for the information to be displayed
echo "Information for" $username
echo "--------------------------------------------------------------------"


awk -v varname="var" -f passwd.awk /etc/passwd
awk -f shadow.awk /etc/shadow







BEGIN { FS = ":" }


/"variable"/{print "Username\t\t\t" $1
print "Password\t\t\tSet in /etc/shadow"
print "User ID\t\t\t\t"$3
print "Group ID\t\t\t"$4
print "Full Name\t\t\t"$5
print "Home Directory\t\t\t"$6
print "Shell\t\t\t\t"$7
}

I need to use the variable I get from the shell script and put it in the awk script to search the passwd file for the certain user and display the said information, but am unsure how it works. I don't full understand how to use the -v command and where to put it in the awk script.

  • 1
    Although it is asked by a different user, this question has a lot in common with [`awk` inside shell script to display `/etc/passwd` info](http://stackoverflow.com/questions/23587928/awk-inside-shell-script-to-display-etc-passwd-info). I'm not convinced that parsing the password file has much in common with 'scientific Linux'. – Jonathan Leffler May 11 '14 at 22:34

3 Answers3

1

If all you need to do is pass shell variable $username to awk as awk variable varname:

awk -v varname="$username" -f passwd.awk /etc/passwd

Inside your awk program you can then refer to varname (without $), which will return the same value that $username has in the shell context.

Since /etc/passwd is :-separated and the username is the 1st field, here's how you could match against the username field specifically:

awk -F: -v varname="$username" -f passwd.awk /etc/passwd

Then, inside passwd.awk, you can use the following pattern:

$1 == varname 
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Then in the awk script varname would already be defined as the $username, correct? – user3626271 May 11 '14 at 20:14
  • Correct (as the _value_ of `$username`) - see my update. – mklement0 May 11 '14 at 20:16
  • I tried that and I put varname="$username" and then in my awk script inside the search // so it shows /varname/{print.... And it doesn't return anything – user3626271 May 11 '14 at 20:20
  • @user3626271: That's not a valid test; `/varname/` would test for the _literal_ `"varname"` (a regex containing only literal chars.) - you'd have to use `$0 ~ varname` instead. (If you just want to see what variable value is being passed to `awk`, use `awk -v varname="$username" 'BEGIN { print "[" varname "]" }'`) – mklement0 May 11 '14 at 20:25
  • So i put $0 ~ varname then do /$0/ ? – user3626271 May 11 '14 at 20:27
  • @user3626271: Use `$0 ~ varname` **instead of** `/varname/` - you need the former form to match against regexes contained in _variables_; the latter only works with regex _literals_. Also see my update re use of `:` as the input field separator and `$1` to match against the username field specifically. – mklement0 May 11 '14 at 20:36
0

Regarding only the awk-part: you can simply use the variable inside your execution part.

Example: awk -v varname="var" -v user="David" '$1==user {print varname;}"'

davidhigh
  • 14,652
  • 2
  • 44
  • 75
  • This doesn't help me because I'm using the inputted username to search for that certain line in the passwd file to display all the info for the user that was inputted. – user3626271 May 11 '14 at 20:00
  • To help you, please provide a more detailed question. Up to now it was only something like "I don't understand the awk -v option." – davidhigh May 11 '14 at 20:02
0

Your script is almost correct. Change the shell command to:

awk -v username="$username" -f passwd.awk /etc/passwd

And then in the awk script:

$1 == username { print "Username\t\t\t" $1
...
}

Using $1 == username is better than $1 ~ username because it's more accurate. For example, if username=john, and you have other similar usernames in /etc/passwd like johnson, johnny, eltonjohn, they will all match. Using $1 == username will be a strict match.

Also, this is not so good:

grep -i $x /etc/passwd

The -i flag makes this a case-insensitive match, but usernames in UNIX are case sensitive (john and John are NOT the same thing). Just drop the -i flag to be more accurate.

Finally, the first part of your script can be shorter and cleaner:

#!/bin/bash
# This tells you that the script must be run by root.
if [ $(id -u) != 0 ]; then
    echo "This script must be run as root!" >&2
    exit 1
fi

while :; do
    # This asks for the user's input for a username.
    echo -n "Enter a username: "
    read username

    # This if block checks if the username exists.
    if grep ^$username:x: /etc/passwd > /dev/null; then
        break
    else
        echo "That user does not exist!"
    fi
done

Basically I removed unnecessary elements, quotations, and simplified expressions, and made the grep even more strict, and cleaned up the format a little.

janos
  • 120,954
  • 29
  • 226
  • 236