PHP preg_match_all: как исключить целые строки, если они содержат шаблон? - PullRequest
1 голос
/ 01 января 2012

Я пытаюсь выяснить, как изолировать все строки точкой с запятой, если они не содержат двоеточий для дальнейшей работы с регулярными выражениями. Прямо сейчас я использую обходной путь, потому что все строки, которые не содержат точки с запятой или двоеточия, также содержат скобку "(". Итак, я просто игнорирую любую строку, содержащую скобку. Код, который у меня есть, на самом деле не работает :

<?php
$filename = "fakexample.txt";
$file = fopen($filename, "rb");
$myFile = fread($file, filesize($filename));

function get_lines($string, $myFile){
  preg_match_all("/$string/m", $myFile, $matches);
  return $matches;
}

$string = "^((?!:|\().)*$";
$list = get_lines($string, $myFile);

foreach($list[1] as $list){
  echo $list."\n";
}
?>

Я беспокоюсь, что это может быть не синтаксис PHP? Возможно, почему это не работает?

Вывод, который я получаю: d.

Ввод:

vulture (wing)
tabulations: one leg; two legs; flying
father; master; patriarch    
mat (box)
pedistal; blockade; pilar
animal belly (oval)
old style: naval
jackal's belly; jester
slope of hill (arch)
key; visible; enlightened

Ответы [ 2 ]

2 голосов
/ 02 января 2012

Это может помочь:

<?php
$filename = "fakexample.txt";
$file = fopen($filename, "rb");
$myFile = fread($file, filesize($filename));

function get_lines($string, $myFile){
  if (preg_match_all("/$string/m", $myFile, $matches))
    return $matches[0];
  else return array();
}

// Match lines with ; but no :
$string = '^[^;:\r\n]*;[^:\r\n]*$';
$lines = get_lines($string, $myFile);

foreach($lines as $line){
  echo $line."\n";
}
?>

Дополнительно:

Вот разбивка вышеприведенного регулярного выражения, которое соответствует точным исходным требованиям, указанным в вопросе: т.е. «... изолировать все строки точкой с запятой, если они не содержат двоеточий ...»

$re = '/ # Match line with ; but no :
    ^           # Anchor to start of line.
    [^;:\r\n]*  # Zero or more non-:, non-;
    ;           # Match one ; (minimum required).
    [^:\r\n]*   # Zero or more non-:.
    $           # Anchor to end of line.
    /xm';

Но поскольку вы настаиваете на использовании выражения: '^((?!(:|\()).)*$', получается, что вы на самом деле нужно сопоставить: "строки без двоеточий и левых скобок." (именно это и делает это выражение).(Вы, наверное, уже это понимаете, но мне всегда нравится писать выражения с полным комментарием - не могу с собой поделать!) Так что здесь это разбивается:

$re = '/ # Match line with no colons or left parentheses.
    ^           # Anchor to start of line.
    (           # Step through line one-char at a time.
      (?!       # Assert that this char is NOT...
        (:|\()  # either a colon or a left paren.
      )         # End negative lookahead.
      .         # Safe to match next non-newline char.
    )*          # Step through line one-char at a time.
    $           # Anchor to end of line.
    /xm';

Если это то, что вы действительно хотите, хорошо.Но если это так, то приведенное выше выражение может быть значительно упрощено (и ускорено) как:

$re = '/ # Match line with no colons or left parentheses.
    ^           # Anchor to start of line.
    [^:(\r\n]*  # Zero or more non-:, non-(, non-EOL.
    $           # Anchor to end of line.
    /xm';

И просто ради полноты, если то, что вы на самом деле, действительно необходимо сопоставить строки , "содержащие хотя бы одну точку с запятой, но без двоеточий или левых скобок" Тогда эта команда сделает следующее:

$re = '/ # Match line with ; but no : or (
    ^            # Anchor to start of line.
    [^;:(\r\n]*  # Zero or more non-:, non-;, non-(.
    ;            # Match one ; (minimum required).
    [^:(\r\n]*   # Zero or more non-:, non-(.
    $           # Anchor to end of line.
    /xm';

Когда работа с регулярным выражением чрезвычайно важна для точно определяют требования заранее в вопросе.Регулярные выражения - очень точный язык, и они будут делать только то, что от них требуется.

Надеюсь, это поможет!

0 голосов
/ 01 января 2012

(?<=;|^)[^;]*(?=;)|(?<=;)[^;]*(?=;|$)

Это должно работать, хотя это будет соответствовать пустым строкам, таким как строка между ;;, если вы не хотите, чтобы это поведение, просто замените звездочки на знаки плюс.

...