0

Im trying to write an awk line in my shell script that will search for the passwd files information belonging to the user that was inputted. Since awk only searches in specific columns and the fact that the first column will vary based on whoever username is used, i think i have to use the script input $username inside the awk line.

So far the line in the script is:

awk -f awkpass.awk /etc/passwd

And the line in the awkpass.awk file is:

/anyone/{print "Username\t\t\t" $1

I think i need to insert $username instead of "anyone" since $username is the variable that i used to recieve input from the user but not quite sure. Help is very appreciated. Thanks!

SiegeX
  • 135,741
  • 24
  • 144
  • 154
Austyn0550
  • 29
  • 2
  • These types of questions are best answered if you give sample input and desired output. It's not clear if you just want to output the entire line in `/etc/passwd` that matches the input username or if you want to parse the various fields that belong to the user. – SiegeX May 11 '14 at 01:17
  • Also, apart from the obvious syntax error (missing `}`), `/etc/passwd` is a delimited file (`:`). Please explain if you want `awk` to accept user input or is your shell script doing that already? – jaypal singh May 11 '14 at 01:20
  • possible duplicate of [Can we use shell variables in awk?](http://stackoverflow.com/questions/15786777/can-we-use-shell-variables-in-awk) – oberlies May 11 '14 at 13:45

2 Answers2

3

You can probably use either of these:

awk -F: "\$1 ~   /$username/  { print \"Username:\t\t\t\", \$1}"
awk -F: "\$1 == \"$username\" { print \"Username:\t\t\t\", \$1}"

where the backslash before $1 protects the $ from the shell, and the backslash before the double quotes protects them from the shell. There are times when it is worth using -f awk.script; it is not clear that this is one of them.

The difference between the ~ and the == notation is that the ~ variant matches using a regex. The version using the == goes for simple equality, of course. Using a match means you could have username='^(root|daemon|bin|sys)$' and you'd get the entries for the four named users in a single invocation of the script. The downside is that if you specify just root, you might get multiple entries (for example, on my Mac, I get both root and _cmvsroot listed).

These scripts use double quotes so that the username can be embedded into the script from the command line. However, as correctly pointed out by Ed Morton in his comment, this leads to a surfeit of backslashes in the script. I generally use single quotes around scripts (despite not doing so in the first edition of this answer).

awk -F: '$1 ~  /'"$username"'/ { print "Username:\t\t\t", $1}'
awk -F: '$1 == "'"$username"'" { print "Username:\t\t\t", $1}'

Those quote sequences are subtle; it is better to avoid them. You can do that by specifying initial values for variables on the command line with -v varname="value" notation. Therefore, you could also use:

awk -F: -v username="$username" \
    "\$1 == username { print \"Username:\t\t\t\", \$1}" /etc/passwd

or, better, since it uses single quotes around the script:

awk -F: -v username="$username" \
    '$1 == username { print "Username:\t\t\t", $1}' /etc/passwd

This sets the awk variable username from the shell variable $username. This variation can be used with a file:

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

with awk.script containing:

$1 == username { print "Username\t\t\t", $1 }
Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Don't use double quotes to delimit awk scripts as it creates a quoting and escaping mess and otherwise complicates your script. See `"\$1 == username { print \"Username:\t\t\t\", \$1}"` vs `'$1 == username { print "Username:\t\t\t", $1}'` and not the difference between what's suggested for the command line above vs within a script file. – Ed Morton May 11 '14 at 14:31
  • @EdMorton: True...I've updated my answer. Thanks for waking me up. Even a casual study of other answers I've made on `awk` will show that I don't often use double quotes around the scripts. – Jonathan Leffler May 11 '14 at 15:17
  • Yup, I figured it was a lack of caffeine. Talking of which :-) - if you're going to use an RE you need to anchor it, `$1 ~ /^'"$username"'$/`. Not that I'd recommend that approach, of course. Finally - `-vvar=..` with no space between `-v` and `var` is gawk-specific so best to either add a space or mention that. – Ed Morton May 11 '14 at 15:23
  • Optional space between a single letter option `-v` and the value (`var=value` in this context) is normal behaviour. At the least, BSD `awk` also allows `-vusername="$username"` because I tested with that and not GNU `awk`. Yes, the `~` is a pattern match; with `username=root`, the scripts with the `~` produce two rows of output (for `root` and `_cvmsroot`) on my Mac. The equality version produces just the one row, of course. I think at one point I had `$0 ~ /username/` and then retreated to `$1` and ... – Jonathan Leffler May 11 '14 at 15:43
  • If BSD awk supports it then that's the only other one I've heard of that does. nawk doesn't, nor does /usr/xpg4/bin/awk, for example. wrt the `~`, right - I'm just suggesting you anchor it with start/end of string anchors, `^` and `$` to avoid the partial match. – Ed Morton May 11 '14 at 17:28
  • I can't reproduce the `-vvariable=value` behaviour on BSD `awk`; it appears to be as fussy as other non-GNU variants. I must have been working with GNU `awk` as the first version of `awk` on my PATH without realizing it. Or I may have been remote logged in to a Linux box without realizing. – Jonathan Leffler May 11 '14 at 19:11
1

Alternatively, you can use getent:

printf "Username: \t\t\t%s\n" "$(getent passwd "$username" | cut -d: -f1)"
glenn jackman
  • 238,783
  • 38
  • 220
  • 352