2017-01-06 1 views
2

Ich brauche Hilfe, um eine Regex, in PHP, um die Anzahl der Ausrufezeichen, die vor und nach einem Wort erscheinen, zu verfeinern. Wörter können in dieser Situation sind alle Zeichen außer einem Raum (sogar Ausrufezeichen), wie folgt (ich die erwartete „vor, nach“ zeige, zählt):PHP Regex - Anzahl der Ausrufezeichen vor und nach einem Wort

!!!!Hi!! => 4, 2 
!!!!Hi => 4, 0 
!Hi!!! => 1, 3 
!easdf.kjaf!! => 1, 2 
!hjdfa!sdfk!jaf!! => 1, 2 
!,!!!!!fdgsdfg!!sdgj => 1, 0 
!!!,!ksfgfdg!jkft!!! => 3, 3 

Wie die Regex codieren, so dass, für die Vorher, hört es auf, nach fortlaufenden Ausrufezeichen zu suchen, wenn irgendein Nichtausrufezeichen erreicht wird, und fängt an, für das after zu zählen, wenn nur Ausrufezeichen übrig bleiben?

Der schwierige Teil ist, wenn Interpunktionszeichen innerhalb des Wortes erscheinen. Diese sollten ignoriert werden, diese werden als Teil des Wortes betrachtet.

Hier ist, wo ich bin:

preg_match_all('/(!*)\b(\S+)\b(!*)/', $w, $m); 

$ w das Wort ist (wie oben dargestellt), wird $ m Array passende

Als Beispiel "!! Hallo!" würde in $ m entsprechen

Array 
(
    [0] => Array 
     (
      [0] => !!Hi! 
     ) 
    [1] => Array 
     (
      [0] => !! 
     ) 
    [2] => Array 
     (
      [0] => Hi 
     ) 
    [3] => Array 
     (
      [0] => ! 
     ) 
) 

Das ist richtig und was ich suche. Wenn ein Interpunktionszeichen das Wort beginnt oder beendet, werden die Dinge jedoch abgeworfen. Der Regex-Anker "\ b" erkennt dies nicht als Teil des Wortes an (wie in dieser Übung definiert). Hier ist ein Beispiel für ein Fehler beim Parsen des Wortes "!!!!!!!! xd.sfgdx !!!, !!"

Array 
(
    [0] => Array 
     (
      [0] => !!!!!!!!xd.sfgdx!!! 
     ) 
    [1] => Array 
     (
      [0] => !!!!!!!! 
     ) 
    [2] => Array 
     (
      [0] => xd.sfgdx 
     ) 
    [3] => Array 
     (
      [0] => !!! 
     ) 
) 

Hilfe, bitte.

+0

Start ist '^', Ende ist '$' –

+0

Warum nicht einfach eine Liste von verbotenen Zeichen erstellen und eine str_replace ausführen, um die Dinge zu bereinigen, bevor die Fancy Regex ausgeführt wird? –

Antwort

3

Sie brauchen nur Anker (^ für Anfang und $ für Ende) und im Grunde alles in der Mitte. Mit Anker wird eine mittlere ! nicht übereinstimmen, wenn es nicht an beiden Enden ist. Dies könnte ein erster Versuch sein;

/^(!*).*(!*)$/ 

Das Problem mit dem etwas hier in der Mitte (.*) ist, dass es gierig ist, und (!*) Vorrang vor der letzten Gruppe nehmen. Das alles in der Mitte würde alles bis zum Ende und die Gruppe einfach nichts zusammenbringen. Einfach obwohl zu beheben, stellt nur die mittlere un-gierig:

/^(!*).*?(!*)$/ 

Jetzt wird es jeden ! am Anfang übereinstimmen, so viel wie möglich, so etwas in der Mitte Schritt für Schritt, bis die nächsten Bedingung Treffer (! Am Ende).

+0

Hier ist ein Online-Test: https://regex101.com/r/w5szXb/1 – sidyll

0

verwenden regexp:

preg_match_all('/^(!*)[^!]{1}.*[^!]{1}(!*)/', $w, $m); 

Für Sie Beispiele Ausgänge sind:

Array 
(
    [0] => Array 
     (
      [0] => !!!!Hi!! 
     ) 

    [1] => Array 
     (
      [0] => !!!! 
     ) 

    [2] => Array 
     (
      [0] => !! 
     ) 

) 

Array 
(
    [0] => Array 
     (
      [0] => !!!,!ksfgfdg!jkft!!,! 
     ) 

    [1] => Array 
     (
      [0] => !!! 
     ) 

    [2] => Array 
     (
      [0] => ! 
     ) 

) 
+0

Vielen Dank. Das hat so gut funktioniert wie gehofft ... obwohl es kaputt geht wenn die Saite entweder "!!!!!!!!!!!!" oder wenn es nur ein Zeichen in einem Strauß Ausrufezeichen in der Zeichenfolge "... !!!!!! N !!!!!!!! ...." gibt. – zardox

2

Hier ist eine kurze nicht-regex Lösung, nur weil:

$test = ['!!!!Hi!!', 
     '!!!!Hi', 
     '!Hi!!!', 
     '!easdf.kjaf!!', 
     '!hjdfa!sdfk!jaf!!', 
     '!,!!!!!fdgsdfg!!sdgj', 
     '!!!,!ksfgfdg!jkft!!!']; 

foreach($test as $str) { 
    $count = $rcount = 0; 
    for ($i = 0; $i < strlen($str); $i++) { 
     if ($str[$i] == '!') { 
      $count += 1; 
      continue; 
     } 
     break; 
    } 

    for ($i = strlen($str) - 1; $i > 0; $i--) { 
     if ($str[$i] == '!') { 
      $rcount += 1; 
      continue; 
     } 
     break; 
    } 
    echo $str . ': ' . $count . ', ' . $rcount . '<br />'; 
} 

Ausgang:

!!!!Hi!!: 4, 2 
!!!!Hi: 4, 0 
!Hi!!!: 1, 3 
!easdf.kjaf!!: 1, 2 
!hjdfa!sdfk!jaf!!: 1, 2 
!,!!!!!fdgsdfg!!sdgj: 1, 0 
!!!,!ksfgfdg!jkft!!!: 3, 3 
+0

Danke für die Hilfe. Ich hatte nach einer reinen Regex-Lösung gesucht, aber als ich überwältigt wurde, nahm ich etwas nach dem, was Sie für mich getan hatten. – zardox

Verwandte Themen