【问题标题】:Negative lookahead -- At the begining of the string负前瞻——在字符串的开头
【发布时间】:2017-03-27 14:15:01
【问题描述】:
我想在 Ruby 中进行字符串替换,但前提是不满足某些条件。
当行不以#include 语句开头时,将所有出现的“allegro4”替换为“allegro”。我试过这个,但我没有任何成功。替换根本没有完成。
"#include <allegro4/allegro4.h>".gsub(/(?!#include) allegro4/, 'allegro')
查看其他负前瞻示例并在 irb 中尝试不同的事情让我相信,特别是在字符串开头的负前瞻有一些奇怪的事情发生。
【问题讨论】:
标签:
ruby
regex
negative-lookahead
【解决方案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>"