正则表达式匹配,不包括括号内的字符

时间:2012-03-11 16:33:26

标签: ruby regex

我有以下类型的字符串。

BILL SMITH (USA)
WINTHROP (FR)
LORD AT WAR (GB)
KIM SMITH

使用这些字符串,我有以下约束: 全部大写 2.可以长2到18个包机 3.最后不应有任何空格或回车 4.应排除在parens内的国家缩写 5.有些名字不会有国家,也应该匹配

在应用我的正则表达式后,我想得到以下内容:

BILL SMITH (USA)  => BILL SMITH
WINTHROP (FR) => WINTHROP
LORD AT WAR (GB) = LORD AT WAR
KIM SMITH => KIM SMITH

我提出了以下正则表达式,但我没有得到任何匹配:

String.scan(\([A-Z \s*]{1,18})(^?!(\([A-Z]{1,3}\)))\)

我一直在敲打这个问题,所以如果有人能指出错误,我会很感激。

更新:

然而,我得到了一些很好的回答,到目前为止,没有任何正则表达式解决方案满足所有约束条件。棘手的部分似乎是一些字符串在括号中有国家而有些则没有。在一种情况下,没有国家的字符串没有匹配,而在另一种情况下,它返回正确的字符串以及没有括号的国家缩写。 (请参阅第二个回复的评论。)一点澄清:我将匹配的所有字符串都将是字符串的起点。不确定这是否有帮助。再次感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

这是一个解决方案:

^((?:[A-Z]|\s){2,18}+?)(?:\s\([A-Z]+\))?$

Rubular上查看。请注意,它在括号之前计算18个字符 - 不确定您希望它如何特定地表现。如果你想确保整行不超过18个字符,我建议你做unless line.length < 18 ...同样,如果你想确保最后没有空格,我建议你使用{{1 }}。这将大大降低您所需的Regexp的复杂性,并使您的代码更具可读性。

编辑:在名称后面没有使用括号时也可以使用。

答案 1 :(得分:1)

最大的错误是你写的(^?!...)代表(?=...)。前者表示“一个可选的起始线锚点,后跟!,后跟...,位于捕获组内”;后者表示“字符串中...后面的位置”。解决这个问题,以及其他一些调整,并添加初始字符串以字母结尾的要求,我们得到:

[A-Z\s]{1,17}[A-Z])(?=\s*\([A-Z]{1,3}\)

基于OP注释

更新:由于这将始终在字符串的开头匹配,因此您可以使用\A将模式“锚定”到字符串的开头。然后你可以摆脱先行断言。这样:

\A[A-Z][A-Z\s]{0,16}[A-Z]

匹配字符串开头,后跟大写字母,后跟最多16个字符,大写字母或空白字符,后跟大写字母。

答案 2 :(得分:1)

您也可以使用gsub删除您不想要的部分。要删除括号中的所有内容,您可以执行以下操作:

str.gsub(/\s*\([^)]*\)/, '')