merlyn tty/42 Dec 7 19:41
rootbeer console Dec 2 14:15
rootbeer tty/12 Dec 6 23:00
The left column is the username, the middle column is the tty name
(that is, the name of the user's connection to the machine),
and the rest of the line is the date and time of login (and possibly
remote login information, but not in this example). In a scalar
context, we get all that at once, which we would then need to split
up:
my $who_text = `who`;
But in a list context, we automatically get the data broken up by
lines:
my @who_lines = `who`;
We'll have a number of separate elements in
@who_lines, each one terminated by a newline. Of
course, adding a chomp around the outside of
that will rip off those newlines, but let's go a different
direction. If we put that as part of the value for a
foreach, we'll iterate over the lines
automatically, placing each one in $_:
foreach (`who`) {
my($user, $tty, $date) = /(\S+)\s+(\S+)\s+(.*)/;
$ttys{$user} .= "$tty at $date\n";
}
This loop will iterate three times for the data above. (Your system
will probably have more than three active logins at any given time.)
Notice that we've got a regular expression match, and in the
absence of the binding operator ("=~"),
that's matching against $_, which is good
because that's where the data is.
However, this regular expression match is in a list context, so
instead of returning back a true/false value (as when you have a
regular expression match in a scalar context), we take the memory
variables and bundle them up in sequence as a list. In this case, the
right side of that assignment is thus a three-element list, which
happens to correspond to the three elements of the literal list on
the left, and we get those nice corresponding assignments. So,
$user ends up being "merlyn",
and so on.