PHP preg_match_all:如果包含模式,我如何排除整行?

时间:2012-01-01 06:19:48

标签: php regex preg-match preg-match-all

我正在试图找出如何用分号隔离所有行,如果它们不包含冒号以进行进一步的正则表达式工作。现在我正在使用一个解决方法,因为所有不包含分号或冒号的行也包含一个括号“(”。所以,我只是忽略包含括号的任何行。我实际上不能使用的代码:

<?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 个答案:

答案 0 :(得分:2)

这可能会起到作用:

<?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';

使用正则表达式对于正确在问题中预先定义要求非常重要。正则表达式是一种非常精确的语言,它们只会按照它们的要求执行。

我希望这有帮助!

答案 1 :(得分:0)

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

这应该有用,虽然它会匹配空字符串,例如;;之间的字符串,如果你不想要这种行为,只需将星号改为加号。