blackparrot
blackparrot

Reputation: 147

regex search line not contain string preceding another

I need a regex to find lines of a file containing a string that is not preceded by another.

Specifically, I need to search for lines that contain the "fixed" string but they do not come preceded by "#" in any previous position. Examples:

fixed xxx
# fixed yyy
aaa # fixed zzz
fixed www # bbb

Regexp should return only this lines:

fixed xxx
fixed www # bbb

Can this be done with a single regex? How?

I'm using PHP.

Thank you all.

PD: Sorry for my English.

Upvotes: 1

Views: 104

Answers (5)

s3v3n
s3v3n

Reputation: 8446

This is the regex you need (without using any lookarounds):

/^[^#\n]*fixed[^\n]*$/m

Explanation:

^ - beginning of a line
[^#\n]* - any amount of chars that are not "#" and are not line breaks
fixed - the string itself
[^\n]* - any other characters that are not line breaks
$ - until the end of a line
/m - multiline modifier: http://php.net/manual/ro/reference.pcre.pattern.modifiers.php

In PHP:

$lines = "fixed xxx\n# fixed yyy\naaa # fixed zzz\nfixed www # bbb";
$matches = array();
preg_match_all('/^[^#]*fixed.*$/m', $lines, $matches);

var_dump($matches);

Result:

array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(9) "fixed xxx"
    [1]=>
    string(15) "fixed www # bbb"
  }
}

thx to @sln for the suggestions.

Upvotes: 3

Bryan Elliott
Bryan Elliott

Reputation: 4095

Or the negative lookbehind way:

(?<!#\s)fixed.*

Example:

http://regex101.com/r/rR4eG1

PHP:

$string = "fixed xxx
# fixed yyy
aaa # fixed zzz
fixed www # bbb";

preg_match_all("/(?<!#\s)fixed.*/", $string, $matches);

print_r($matches);

Output:

Array
(
    [0] => Array
        (
            [0] => fixed xxx
            [1] => fixed www # bbb
        )
)

Upvotes: 0

user557597
user557597

Reputation:

This approach checks from the end of line back to beginning.
Incase of fixed # fixed

 #  '/^(?!.*\#.*fixed).*fixed.*/m'

 ^ 
 (?! .* \# .* fixed )
 .* 
 fixed
 .* 

Upvotes: 0

rullof
rullof

Reputation: 7434

Use Regex Negative Lookbehind: Live Demo

$reg = '/(?<!\#\s)(fixed.+)/';

$input = '
fixed xxx
# fixed yyy
aaa # fixed zzz
fixed www # bbb';

preg_match_all($reg, $input, $output);
$output = $output[0];

print_r($output);

Output:

Array
(
    [0] => fixed xxx
    [1] => fixed www # bbb
)

Upvotes: 0

Garrett Openshaw
Garrett Openshaw

Reputation: 304

Since the comparisons are all by line, I would try something like this...

(in pseudo code)

Regex regex = new Regex("^[0-9]"); //a string that starts with a number
string thisLine = input.getLine();

while(hasInput)
{
   string lastLine = thisLine;
   string thisLine = input.getLine();
   if(regex.hasMatch(lastLine)) 
   {
       System.out.println(thisLine)
   }
}

Upvotes: 0

Related Questions