我有以下类型的字符串。
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}\)))\)
我一直在敲打这个问题,所以如果有人能指出错误,我会很感激。
更新:
然而,我得到了一些很好的回答,到目前为止,没有任何正则表达式解决方案满足所有约束条件。棘手的部分似乎是一些字符串在括号中有国家而有些则没有。在一种情况下,没有国家的字符串没有匹配,而在另一种情况下,它返回正确的字符串以及没有括号的国家缩写。 (请参阅第二个回复的评论。)一点澄清:我将匹配的所有字符串都将是字符串的起点。不确定这是否有帮助。再次感谢您的帮助。
答案 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}\)
更新:由于这将始终在字符串的开头匹配,因此您可以使用\A
将模式“锚定”到字符串的开头。然后你可以摆脱先行断言。这样:
\A[A-Z][A-Z\s]{0,16}[A-Z]
匹配字符串开头,后跟大写字母,后跟最多16个字符,大写字母或空白字符,后跟大写字母。
答案 2 :(得分:1)
您也可以使用gsub
删除您不想要的部分。要删除括号中的所有内容,您可以执行以下操作:
str.gsub(/\s*\([^)]*\)/, '')