在使用正則表達式在匹配文本時,除了可以通過表達式捕獲命中的文本串外,還可以對捕獲的文本串進行命名。尤其是在解析日志的場景中,經常會被用到。表達式如下:
\<(?<pri>\d+)\>(?<time>.*) (?<host>\S+) (?<detail>Log.*)
該表達式對文本串匹配后會有四個捕獲組,它們依次分別被命名為pri, time, host以及detail。在Java語言目前提供的正則表達式相關的類中,沒有公共方法可以枚舉這些命名捕獲。即沒有方法可以像用捕獲組的下標一樣來遍歷捕獲組。這無疑為使用者帶來了一定的麻煩。
不過,通過仔細翻看Pattern的代碼實現。不難看到,其實Patter對象內部有一個包內可見方法“namedGroups”。該方法返回一個捕獲組的名字與捕獲組對應下標的Map對象。可以通過訪問Map對象的Key集合獲得所有捕獲組的名字。然后枚舉捕獲組的名字獲得每個捕獲的值。
下面,我們利用Java的反射機制獲得捕獲組名字與索引映射的Map:
public Map<String, Integer> getNamedGroups(Pattern pattern) {try {Method namedGroup = ReflectionUtils.getMethod(Pattern.class,"namedGroups");namedGroup.setAccessible(true);return (Map<String, Integer>) namedGroup.invoke(pattern);} catch (Exception e) {throw new IllegalArgumentException(e);}}
拿到捕獲組的命名Map后,就可以根據程序需要進行后續的訪問應用了。