否定前瞻 - 在弦的开头

时间:2016-11-14 00:23:51

标签: ruby regex negative-lookahead

我想在Ruby中进行字符串替换,但仅当某些条件 不符合时才会进行。

当行不以#include语句开头时,将'allegro4'的所有出现替换为'allegro'。我试过这个,但我没有成功。替换根本就没有完成。

"#include <allegro4/allegro4.h>".gsub(/(?!#include) allegro4/, 'allegro')

irb中查看负向前瞻和尝试不同事物的其他示例,让我相信,在字符串的开头专门用负面预测会有一些奇怪的事情发生。

1 个答案:

答案 0 :(得分:1)

R = /
    \A              # match beginning of string
    (?!\#include)   # do not match '#include' at start of string (negative lookahead)
    .*?             # match any number of any character
    <               # match '<'
    \K              # forget everything matched so far
    allegro         # match string
    (\d+)           # match one or more digits in capture group 1
    \/allegro       # match string
    \1              # match the contents of capture group 1
    /x              # Free-spacing regex definition mode

def replace_unless(str)
  str.gsub(R, 'allegro/allegro') 
end

replace_unless "cat #include <allegro4/allegro4.h>"
  #=> "cat #include <allegro/allegro.h>" 
replace_unless "cat #include <allegro4/allegro3.h>"
  #=> "cat #include <allegro4/allegro3.h>"
replace_unless "#include <allegro4/allegro4.h>"
  #=> "#include <allegro4/allegro4.h>" 

我假设特定字符串'allegro'要匹配,并且任何非负整数都可以跟随'allegro'的两个实例,但是在'allegro'的两个实例之后不能有不同的数字。如果该号码必须为4,请将正则表达式中的(\d+)\1替换为4。如果'allegro'只是一个小写字母串的替身,那么正则表达式可以改变如下。

R = /
    \A              # match beginning of string
    (?!\#include)   # do not match '#include' at start of string (negative lookahead)
    .*              # match any number of any character
    <               # match character
    \K              # forget everything matched so far
    ([[:lower:]]+)  # match one or more lower-case letters in capture group 1
    (\d+)           # match one or more digits in capture group 2
    \/              # match character
    \1              # match the contents of capture group 1
    \2              # match the contents of capture group 2
    /x              # Free-spacing regex definition mode

def replace_unless(str)
  str.gsub(R, '\1/\1') 
end

replace_unless "cat #include <cats9/cats9.h>"
  #=> "cat #include <cats/cats.h>" 
replace_unless "dog #include <dogs4/dogs3.h>"
  #=> "dog #include <dogs4/dogs3.h>" 
replace_unless "#include <pigs4/pigs4.h>"
  #=> "#include <pigs4/pigs4.h>"