3

I am using

ps -l -u user

to get the running processes of a given user.

Now, when I want to split the information into arrays in PHP I am in trouble because ps outputs the data for humans to read without fixed delimiters. So you can't split with space or tab as regex.

So far I can only detect the columns by character positions.

Is there any way in php to split a string into an array at certain positions? Something like:

$array=split_columns($string, $positions=array(1, 10, 14))

to cut a string into pieces at positions 1, 10 and 14?

Juergen Schulze
  • 1,515
  • 21
  • 29

3 Answers3

1

I decided to try a regex approach with dynamic pattern building. Not sure it is the best way, but you can give it a try:

function split_columns ($string, $indices) {
    $pat =  "";
    foreach ($indices as $key => $id) {
        if ($key==0) { 
            $pat .= "(.{" . $id . "})";
        } else if ($key<count($indices)) {
            $pat .= "(.{" . ($id-$indices[$key-1]) . "})";
        }
    }
    $pats = '~^'.$pat.'(.*)$~m';
    preg_match_all($pats, $string, $arr);
    return array_slice($arr, 1);
}
$string = "11234567891234567\n11234567891234567"; // 1: '1', 2: '123456789', 3: '1234', 4: '567'
print_r (split_columns($string, $positions=array(1, 10, 14)));

See the PHP demo

The point is:

  • Build the pattern dynamically, by checkign the indices, subtracting the previous index value from each subsequent one, and append the (.*)$ at the end to match the rest of the line.
  • The m modifier is necessary for ^ to match the start of the line and $ the end of the line.
  • The array_slice($arr, 1); will remove the full match from the resulting array.
  • A sample regex (meeting OP requirements)) will look like ^(.{1})(.{9})(.{4})(.*)$
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
1

I modified Wiktor's solution as I don't need that many information.

function split_columns ($string, $indices) {
    $pat =  "";
    foreach ($indices as $key => $id) {
        if ($key==0) { 
            $pat .= "(.{" . $id . "})";
        } else if ($key<count($indices)) {
            $pat .= "(.{" . ($id-$indices[$key-1]) . "})";
        }
    }
    $pats = '~^'.$pat.'(.*)$~m';
    preg_match_all($pats, $string, $arr, PREG_SET_ORDER);
    $arr=$arr[0];
    return array_slice($arr, 1);
}
Juergen Schulze
  • 1,515
  • 21
  • 29
0

In PHP preg_split will help you here. You can split by a number of whitespaces e.g.:

<?
$text = '501   309     1     4004   0   4  0  2480080  10092 -      S                   0 ??         0:36.77 /usr/sbin/cfpref
  501   310     1 40004004   0  37  0  2498132  33588 -      S                   0 ??         0:23.86 /usr/libexec/Use
  501   312     1     4004   0  37  0  2471032   8008 -      S                   0 ??        19:06.48 /usr/sbin/distno';
$split = preg_split ( '/\s+/', $text);
print_r($split);

If you know the number of columns you can then go through the array and take that number of columns as one row.

Martin Cup
  • 2,399
  • 1
  • 21
  • 32
  • 1
    I already tried it - of course. Point is that ps does not give consistence results when split with spaces. You can end up with 12 array elements in a row and 15 in the next row. E.g. depends if the listed commands in ps include spaces as well. – Juergen Schulze Dec 02 '16 at 14:55
  • 1
    Then you can maybe use the answer from here: http://stackoverflow.com/a/11071688/1768033 and create a format that fits your needs – Martin Cup Dec 02 '16 at 15:11
  • I will have a look at it. Thank you. – Juergen Schulze Dec 02 '16 at 17:36