2016-12-02 2 views
3

ich verwendeSplit Zeichenfolge in Spalte positioniert

ps -l -u user 

die laufenden Prozesse eines bestimmten Benutzers zu erhalten.

Jetzt, wenn ich die Informationen in Arrays in PHP teilen möchte, stehe ich in Schwierigkeiten, weil ps die Daten für Menschen ausgibt, ohne feste Trennzeichen zu lesen. Sie können also nicht mit Leerzeichen oder Tab als Regex teilen.

Bisher kann ich die Spalten nur nach Zeichenpositionen erkennen.

Gibt es eine Möglichkeit in PHP, eine Zeichenfolge in ein Array an bestimmten Positionen zu teilen? Etwas wie:

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

eine Zeichenfolge in Stücke an den Positionen 1, 10 und 14 schneiden?

+0

'preg_match_all ('~^(.) (. {10}) (. {4}) ~ m', $ s, $ Übereinstimmungen)'? –

+0

awk ist hier nützlich –

Antwort

1

Ich entschied mich für einen Regex-Ansatz mit dynamischem Musteraufbau. Nicht sicher, es ist der beste Weg, aber man kann es versuchen:

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))); 

Siehe PHP demo

Der Punkt ist:

  • das Muster dynamisch bauen, indem Sie die Indizes der prüfen, Subtrahieren des vorherigen Indexwerts von jedem nachfolgenden und Anhängen des (.*)$ am Ende, um mit dem Rest der Zeile übereinzustimmen.
  • Der Modifikator m ist erforderlich, damit ^ den Anfang der Zeile und $ das Ende der Zeile entspricht.
  • Die array_slice($arr, 1); wird die vollständige Übereinstimmung aus dem resultierenden Array entfernen.
  • Eine Probe regex (Sitzung OP-Anforderungen)) wird wie folgt aussehen ^(.{1})(.{9})(.{4})(.*)$
+0

Brilliant. Ich modifiziere es ein bisschen, um meinen Bedürfnissen zu entsprechen. Ich brauche kein multidimensionales Array. – Juergen

0

In PHP hilft Ihnen preg_split hier. Sie können durch eine Reihe von Whitespaces z geteilt .:

<? 
$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); 

Wenn Sie die Anzahl der Spalten wissen Sie dann durch das Feld gehen und dass die Anzahl der Spalten als eine Zeile nehmen.

+1

Ich habe es schon versucht - natürlich. Punkt ist, dass ps keine Konsistenz ergibt, wenn es mit Leerzeichen geteilt wird. Sie können mit 12 Array-Elementen in einer Zeile und 15 in der nächsten Zeile enden. Z.B. hängt davon ab, ob die aufgelisteten Befehle in ps auch Leerzeichen enthalten. – Juergen

+1

Dann können Sie vielleicht die Antwort von hier verwenden: http://Stackoverflow.com/a/11071688/1768033 und erstellen Sie ein Format, das Ihren Bedürfnissen entspricht –

+0

Ich werde es mir ansehen. Vielen Dank. – Juergen

1

I Wiktor-Lösung modifiziert, wie ich, dass viele Informationen nicht brauchen.

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); 
}