piecia
piecia

Reputation: 386

Search for lines that do not end with a given character

I'm searching in a file for lines that do not end with a backslash (\), but they must begin with some text, so I've written:

if ( $cur_line =~ m{\A\s+(.+?)(?!\\)\z/xms ){
 ... # parentheses are only for testing
}

But with the above $1 always contains the whole line (without leading spaces) including the backslash at the end. Only the first occurrence of a line without a backslash at the end matches correctly. After this all the lines with trailing backslashes match. Why? What am I doing wrong?

When I use:

if ( $cur_line =~ m{\A\s+[^\\]+(?!\\)\z/xms ){
 ...
}

it works almost correctly however$cur_line then can contain a backslash.

I've checked the following code:

if ( $cur_line !~ m{\\\z}xms ) {

amd it works perfectly. But I'm curious what is wrong with my negative lookahead.

Upvotes: 0

Views: 58

Answers (2)

Borodin
Borodin

Reputation: 126722

It seems most straightforward to write exactly what you described. You asked for "lines that not ending on backslash, but they must beginning on some text".

This looks for the end of the string \z not preceded by a backslash (?<!\\) (the backslash has to be duplicated). And a second regex checks to see that there is a non-space character somewhere in the string.

for ( 'abcdef\\', 'abcdef',  '\\', '' ) {
  printf "'%s' -- %s\n", $_, /(?<!\\)\z/ && /\S/ ? 'match' : 'no match';
}

output

'abcdef\' -- no match
'abcdef' -- match
'\' -- no match
'' -- no match

Beware that checking for things at the end of a line can be questionable because of the trailing newline, so you should chomp each line before you test it. It is up to you what to do about lines that end with, say, a backslash followed by spaces.

Upvotes: 0

alpha bravo
alpha bravo

Reputation: 7948

you could use this pattern if your engine supports negative look-behind

\A\s+(.*)(?<!\\)\z

or this pattern if it does not

\A\s+(.*[^\\])\z

the reason why your first pattern didn't work is because (.+?) has already consumed the last back slash and the last back slash does not see a \ ahead of it

Upvotes: 1

Related Questions