我试图从字符串中获取子字符串 如:
测试字符串:
cat_zoo_New_York_US
dog_zoo_South_Carolina
dolphin_zoo_Montreal_Canada
pokemon_home_d_K2-155
返回子字符串:
cat, New_York
dog, South_Carolina
dolphin, Montreal
pokemon, d
我试过的正则表达式是
([\w]+)(?:(_zoo_|_home_))(((?!(_US|_Canada|_K2-155))\w)+)
我不认为它非常简洁,除了我需要的东西之外还返回其他子字符串。你有什么其他的建议? 谢谢!
首先,我喜欢将([^_]+)
和(?:)
同时用于示例字符串的不同部分。但是,让我扩展一些示例字符串。
cat_zoo_New_York_US
dog_zoo_South_Carolina
yellow_dolphin_zoo_Montreal_Canada
pokemon_home_d_K2-155
pokemon_home_zoo_d_K2-155
我实际上想要使用诸如'zoo','home'或'home_zoo'之类的锚字符串来分隔前后的字符,以及匹配(和丢弃)国家的最后部分(或任何指定的地方) ID),这使得这个问题不那么普遍(我喜欢使用_
的想法,但让我更好地学习它)。
这里有两个问题
(?=)
和.*
的功能是什么?
(?=(?:_US|_Canada|_K2-155|$)).*$
?好像我用了
(?:_US|_Canada|_K2-155|$)
,它仍然可以...... 因为我在锚字符串上稍微扩展了一下,让它支持
_
,我用过:
(.*?)(?:_*)(?:home_zoo|zoo|home)(?:_*)(.*?)(?:_*)(?:US|Canada|K2-155|$)
似乎没问题,但如果我使用:
(.*?)(?:_*)(?:home|zoo|home_zoo)(?:_*)(.*?)(?:_*)(?:US|Canada|K2-155|$)
首先匹配home
最后一个样本字符串。有没有
贪心算法捕获这个而不指定模式的顺序
字符串?
再说一次,我不想制作一长串的锚字符串,但我没有其他的想法,如果没有这样做就更普遍。 再次感谢!
答案 0 :(得分:1)
好吧,我尝试了一种更简单的方法。如果您的数据比上面提供的样本更复杂,则可能会失败。否则,对于上面的文本,它工作正常。
这是我使用的表达式:
^([^_]*)_[^_]*_(.*)_.*$
1 23 45 67
基本上我做的是:
将其替换为\ 1,\ 2(第一组,第二组)。
你可以找到一个小提琴here
如果您正在使用vim,您还可以使用以下命令在vim中实现相同的功能:
:%s/^[^_]*_\([^_]*\)_\(.*\)_.*$/\1, \2/g
<强>更新强>
^([^_]*)_[^_]*_(((?:South_)|(?:New_))*[^_]*)((?:_US)|(?:_Canada)|(?:_K2-155))*$
你可以找到新的小提琴(这里)[https://regex101.com/r/qQ2dE4/273]
这个与前一个有什么区别?
现在,我作弊了一点,因此我寻找形容词,修改州名,如South_或New_。您可以在此处添加更多内容,例如East_,West_,Old_或其他任何内容,如果您的日期有案例。
在某些情况下,数据会跳过国家/地区。加上看起来最后一行的最后一个标记不跟随模式。因此,我在表达式中明确列出了这些选项,如美国,加拿大等。您可能还需要在此处添加更多例外情况。
答案 1 :(得分:1)
你可以这样试试:
^([^_]+)_[^_]+_(.*?)(?=(?:_US|_Canada|_K2-155|$)).*$
这将捕获2组。例如,您可以使用此替代group1, group2
。
首先捕获以组{1}中的下划线结尾的第一部分,如cat_
。然后匹配以zoo_
或home_
等下划线结尾的第二部分。
从那一点开始捕获一个组,直到你使用前瞻(?=
或字符串结尾遇到一个值。
那将匹配:
^
字符串的开头([^_]+)
匹配的捕获组不是_一次或多次(组1) _[^_]+_
匹配_然后不是_一次或多次,后跟_ (.*?)
在群组中捕获任何角色零次或多次贪婪(群组2) (?=
肯定右侧的正面前瞻性
(?:
非捕获组
_US|_Canada|_K2-155|$
您的值或字符串的结尾)
关闭群组)
关闭群组.*$
匹配任何字符零次或多次,直到字符串结尾修改:更新后的问题,或许这符合您的要求:
^(.*?)_(?:home_zoo|zoo|home)(.*?)(?=(?:_US|_Canada|_K2-155|$))
这将匹配任何charcter零次或多次非贪婪(.*?)
,然后是下划线和非捕获组(?:home|zoo|home_zoo)
来分隔前后的字符。