views:

237

answers:

3

I've tried parsing a list of users currently connected via SSH to a server, but the results are very irregular, so I was forced to simply do:

$users = shell_exec('who');
echo "<pre>$users</pre>";

Is there a better way to parse the output of who in the command line before I let PHP mess around with it? I want it in an array which contains the username (first column below), the terminal they're connected on (second column), the date and time they connected (third), and the IP from where they connected (in parenthesis). I'm guessing I should use preg_split to split the data but it seems really irregular sometimes with username length, terminal name, etc..

(some example output of who):

alex     tty7         2010-01-23 17:04 (:0)
alex     pts/0        2010-01-30 17:43 (192.168.1.102)
root     pts/1        2010-01-30 17:45 (192.168.1.102)
A: 

preg_split only needs to match the space between the data, not the data itself:

$who = shell_exec('who');
$users = array();
foreach(split("\n", $who) as $user) {
  $users[] = preg_split("/\s{2,}/", $user); //Match 2 or more whitespace chars
}
Tobias Cohen
+1  A: 

explode()ing on newlines (\n) gives you an array with one item per line, and when you loop through the array, and use preg_split("/\s+/", $sValue, 3), it should give you a new array with every column as an item. Then you need to split the Date and the Addr.

The full code would be something like this:

<?php
$sTempUsers = shell_exec('who');
$aTempUsers = explode("\n", $sTempUsers);

$aUsers = array();
foreach($aTempUsers AS $sUser)
{
    $aTempUser = preg_split("/\s+/", $sUser, 3); // username | terminal | date addr
    preg_match("/^(.+)\s\((.+)\)$/", $aTempUser[2], $aDateAndAddr); // full match | date | addr

    $aUsers[] = array(
        $aTempUser[0], 
        $aTempUser[1], 
        $aDateAndAddr[1], 
        $aDateAndAddr[2]
    ); // username | terminal | date | addr
}
?>

You can find the result in $aUsers.

Douwe Maan
A: 
$who = shell_exec('who');
$s = split("\n",$who);
$func = function($value) { return preg_split("/\s{2,}/",$value ); };
print_r(array_map($func, $s));
ghostdog74