Users who are logged on, in alphabetical order, printed on one line.
What are the minimum amount of changes to get this to work because in a bash script?
this is the given script:
for name in $@
do
who | grep -w "^name" | sed 's/ .*//' | uniq
done | sort | tr '\n' ' '
echo
CodePudding user response:
Single line commands:
who | awk '{print $1}' | sort | uniq | tr '\n' ' '
who: list of logged in users.awk '{print $1}': keep only the first word or each line, which is the usernames.sort: put the usernames in alphabetical order.uniq: remove duplicates.tr '\n' ' ': remove carriage returns, and replace them with spaces.
Ex
$ who
steve tty7 Mar 5 16:25 (:0)
bernard tty7 Mar 5 16:25 (:0)
sarah tty7 Mar 5 16:25 (:0)
$ who | awk '{print $1}' | sort | uniq | tr '\n' ' '
bernard sara steve
Your code did grep -w "^name", which tells grep to output the lines that start with "name". Not the lines that begin with the value of variable "name". For that you would need to do grep -w "^$name".
CodePudding user response:
Try this Shellcheck-clean code:
for name in "$@"
do
who | sed 's/[[:space:]].*//' | grep -xF -- "$name"
done | sort -u | paste -sd ' '
$@should always have double quotes on it ("$@"). See Accessing bash command line args $@ vs $*. Shellcheck correctly complains if double quotes are not used.sed 's/[[:space:]].*//'removes the first whitespace character, and everything after it, on every input line. Using[[:space:]]instead of a literal space character means that the code will still work if thewhooutput uses tabs as separators. It may be easier to read too. Thesedcommand is run first to ensure that usernames occupy whole lines so it's easier to avoid spurious matches at the next pipeline stage.grep -xF -- "$name"searches for whole lines in the input that are the"$name"string. The-xoption forces matching of whole lines. That prevents, for instance, the usernamemarymatching the usernamemary.jane(a valid username on at least some Linux systems). The-Foption means that regular expression patterns in "$name" are treated as literal strings. That prevents, for instance, the namet.mmatching the nametim. The--prevents a leading hyphen in"$name"being treated as agrepoption. No system that I know of allows usernames to have leading hyphens, but there's nothing to stop such an invalid name being provided as a command line argument to the code. The-woption togrepwouldn't be useful here because valid names may contain non-word characters (e.g.t.m).sort -utakes the output of theforloop (an unsorted list of usernames, one per line, possibly with repetitions) and sorts it. The-uoption causes it to remove duplicates (like piping touniq, but saves a process creation).paste -sd ' 'puts all the lines in to input on a single line, separated by spaces (specified by the-doption and' '(space) option argument), and terminated with a newline character.tr '\n' ' 'would have a similar effect but it produces an unterminated line with a trailing space character.
