我正在成功使用正则表达式,但也许有点太成功,我想添加一些例外,我不希望它影响某些词。 (参见我的previous question for some background ...这解决了给定的问题,现在我需要添加例外)。
因此,总而言之,我需要做的是:
[a-z]_[a-z]
的模式,所以像some_var
但不是_var
这样的字词。"this_file.jpg"
。size_t
等等(我有一系列例外情况)。当我找到合适的匹配时,我将其转换为camelCase,基本上是(some_var
- > someVar
),这在前面的问题中得到了成功解答。
这是在Ruby中,这是我到目前为止的代码:
exclusions = ["size_t", "other_t"]
replacement = text.gsub(/"[^"]+"|_[a-z]/) {|match| (match.length > 2)? match : match[1].upcase } # doesn't do any exclusions from my list, only handles the quoted case.
我有点不知所措。我想我需要某种消极的前瞻,但我不确定该怎么做(对正则表达式没有超级经验)。
样品
输入:
this_var "that_var" size_t
输出:
thisVar "that_var" size_t
也就是说,引号中的内容应该不受影响,我的排除列表中的内容也应保持不变。应更改与[a-z]_[a-z]
匹配的任何其他字符串。
答案 0 :(得分:2)
我不知道红宝石,但我可以在这里给出算法。
匹配没有引号的单词可以实现如下(注意:文字正则表达式;在Ruby中做任何必要的事情,使其成为可读的正则表达式):
(?<!")([a-z]+(?:_[a-z]+)*)(?!")
这将匹配禁用的关键字(例如size_t
),但随后您可以随时拥有禁用关键字列表,并尝试查看捕获的组是否与其中一个禁用词匹配。从那时起,它完成了工作。
正则表达式演练:
(?<!") # position where the preceding text is not a double quote
( # start group
[a-z]+ # one character among 'a' - 'z', one or more times, followed by
(?: # begin non capturing group
_ # an underscore, followed by
[a-z]+ # one character among 'a' - 'z', one or more times
) # end non capturing group
* # zero or more times, followed by
(?!") # a position where what immediately follows is not a double quote
答案 1 :(得分:1)
您可以使用lookbehind (?<=..)
来测试您之前有一个字母,并且保留的字长度大于2,因此只需在交替之前添加它们。
text.gsub(/"[^"]+"|size_t|(?<=[a-z])_[a-z]/) {|match| (match.length > 2)? match : match[1].upcase }
注意:lookbehind(或前瞻)是一个只检查子模式但不消耗字符的断言。
另请注意,"[^"]"
可以替换为"(?:[^"]+|(?<=\\)")+"
,以便在需要时允许双引号之间的双引号转义。
很好,ruby正则表达式引擎支持atomic groups和possessive quantifiers。你可以像这样重写你的表达以获得更多的表演:
/"[^"]++"|size_t|(?<=[a-z])_[a-z]/
或
/"(?>[^"]++|(?<=\\)")+"|size_t|(?<=[a-z])_[a-z]/
答案 2 :(得分:1)
我不得不问,是否有令人信服的理由在一个正则表达式中完成所有操作?如果它很重要,我不介意复杂性。但是如果你认为你将不得不做更复杂的解析,那么将其分解为几个步骤可能是值得的。例如,
我的经验也是,一旦你开始尝试进行更复杂的解析,你可能会看到比单纯形正则表达式更复杂的解析器。
答案 3 :(得分:1)
我这样做:
input.gsub /"?[a-z]+_[a-z]+"?/ do |match|
if match[0] == '"' && match[-1] == '"' || blacklist.include?(match)
match
else
match.gsub(/_[a-z]/) { |match| match[1].upcase }
end
end
blacklist
是一系列您不想替换的单词。
测试:
input = 'this_var "that_var" size_t'
blacklist = %w{size_t other_t}
output = input.gsub /"?[a-z]+_[a-z]+"?/ do |match|
if match[0] == '"' && match[-1] == '"' || blacklist.include?(match)
match
else
match.gsub(/_[a-z]/) { |match| match[1].upcase }
end
end
puts output
输出:
thisVar "that_var" size_t