Clojure 重新查找有效,但重新匹配器对相同的字符串模式组合失败
Clojure re-find works but re-matcher fails for the same string-pattern combination
为什么 clojure 的 re-matcher
对于 re-find
适用的相同字符串模式组合会失败?
正则表达式模式:#"\[(?<level>[A-Z]*)\]:\s(?<msg>.*)"
示例字符串:[WARNING]: \tTimezone not set \r\n
下面是控制台上的示例,其中包含上述模式和字符串以及另一个适用于 re-find
和 re-matcher
(具有相同模式)的字符串。
user=> (def s1 "[ERROR]: This is an error.")
#'user/s1
user=> (def s2 "[WARNING]: \tTimezone not set \r\n")
#'user/s2
user=> (def rx #"\[(?<level>[A-Z]*)\]:\s(?<msg>.*)")
#'user/rx
user=> (re-find rx s1)
["[ERROR]: This is an error." "ERROR" "This is an error."]
user=> (re-find rx s2)
["[WARNING]: \tTimezone not set " "WARNING" " \tTimezone not set "]
user=> (def m1 (re-matcher rx s1))
#'user/m1
user=> (def m2 (re-matcher rx s2))
#'user/m2
user=> (.matches m1)
true
user=> (.matches m2)
false
正如您从代码片段中看到的,re-find
适用于字符串 s2
,但是 re-matcher
的 matches
方法 returns false
对于相同的字符串模式组合。
我读到 re-find
在幕后使用 Matcher
方法 (ref),所以我在这里遗漏了什么?
user> (def s1 "[ERROR]: This is an error.")
#'user/s1
user> (def s2 "[WARNING]: \tTimezone not set \r\n")
#'user/s2
user> (def rx #"\[(?<level>[A-Z]*)\]:\s(?<msg>(?s:.)*)")
#'user/rx
user> (re-find rx s1)
["[ERROR]: This is an error." "ERROR" "This is an error."]
user> (re-find rx s2)
["[WARNING]: \tTimezone not set \r\n"
"WARNING"
" \tTimezone not set \r\n"]
user> (def m1 (re-matcher rx s1))
#'user/m1
user> (def m2 (re-matcher rx s2))
#'user/m2
user> (.matches m1)
true
user> (.matches m2)
true
user> (re-groups m2)
["[WARNING]: \tTimezone not set \r\n"
"WARNING"
" \tTimezone not set \r\n"]
正如 Wiktor 所指出的,正则表达式中的 .
与 EOL (end-of-line) 标记不匹配;并且 re-find
找到任何子字符串匹配,而 .matches
on re-matcher
需要完整的字符串匹配。因此,如果您使用 (?s:....)
启用“single-line 模式”,您将获得符合您预期的正则表达式。请参阅上面的正则表达式更改。
但请注意,此正则表达式包括 <msg>
组中的 EOL 字符。如果您不想在 <msg>
组中包含 EOL 字符,请将正则表达式更改为
user> (def rx1 #"\[(?<level>[A-Z]*)\]:\s(?<msg>.*)(?s:.*)")
#'user/rx1
user> (re-find rx1 s1)
["[ERROR]: This is an error." "ERROR" "This is an error."]
user> (re-find rx1 s2)
["[WARNING]: \tTimezone not set \r\n"
"WARNING"
" \tTimezone not set "]
user> (def m3 (re-matcher rx1 s1))
#'user/m3
user> (def m4 (re-matcher rx1 s2))
#'user/m4
user> (.matches m3)
true
user> (.matches m4)
true
user> (re-groups m4)
["[WARNING]: \tTimezone not set \r\n"
"WARNING"
" \tTimezone not set "]
为什么 clojure 的 re-matcher
对于 re-find
适用的相同字符串模式组合会失败?
正则表达式模式:#"\[(?<level>[A-Z]*)\]:\s(?<msg>.*)"
示例字符串:[WARNING]: \tTimezone not set \r\n
下面是控制台上的示例,其中包含上述模式和字符串以及另一个适用于 re-find
和 re-matcher
(具有相同模式)的字符串。
user=> (def s1 "[ERROR]: This is an error.")
#'user/s1
user=> (def s2 "[WARNING]: \tTimezone not set \r\n")
#'user/s2
user=> (def rx #"\[(?<level>[A-Z]*)\]:\s(?<msg>.*)")
#'user/rx
user=> (re-find rx s1)
["[ERROR]: This is an error." "ERROR" "This is an error."]
user=> (re-find rx s2)
["[WARNING]: \tTimezone not set " "WARNING" " \tTimezone not set "]
user=> (def m1 (re-matcher rx s1))
#'user/m1
user=> (def m2 (re-matcher rx s2))
#'user/m2
user=> (.matches m1)
true
user=> (.matches m2)
false
正如您从代码片段中看到的,re-find
适用于字符串 s2
,但是 re-matcher
的 matches
方法 returns false
对于相同的字符串模式组合。
我读到 re-find
在幕后使用 Matcher
方法 (ref),所以我在这里遗漏了什么?
user> (def s1 "[ERROR]: This is an error.")
#'user/s1
user> (def s2 "[WARNING]: \tTimezone not set \r\n")
#'user/s2
user> (def rx #"\[(?<level>[A-Z]*)\]:\s(?<msg>(?s:.)*)")
#'user/rx
user> (re-find rx s1)
["[ERROR]: This is an error." "ERROR" "This is an error."]
user> (re-find rx s2)
["[WARNING]: \tTimezone not set \r\n"
"WARNING"
" \tTimezone not set \r\n"]
user> (def m1 (re-matcher rx s1))
#'user/m1
user> (def m2 (re-matcher rx s2))
#'user/m2
user> (.matches m1)
true
user> (.matches m2)
true
user> (re-groups m2)
["[WARNING]: \tTimezone not set \r\n"
"WARNING"
" \tTimezone not set \r\n"]
正如 Wiktor 所指出的,正则表达式中的 .
与 EOL (end-of-line) 标记不匹配;并且 re-find
找到任何子字符串匹配,而 .matches
on re-matcher
需要完整的字符串匹配。因此,如果您使用 (?s:....)
启用“single-line 模式”,您将获得符合您预期的正则表达式。请参阅上面的正则表达式更改。
但请注意,此正则表达式包括 <msg>
组中的 EOL 字符。如果您不想在 <msg>
组中包含 EOL 字符,请将正则表达式更改为
user> (def rx1 #"\[(?<level>[A-Z]*)\]:\s(?<msg>.*)(?s:.*)")
#'user/rx1
user> (re-find rx1 s1)
["[ERROR]: This is an error." "ERROR" "This is an error."]
user> (re-find rx1 s2)
["[WARNING]: \tTimezone not set \r\n"
"WARNING"
" \tTimezone not set "]
user> (def m3 (re-matcher rx1 s1))
#'user/m3
user> (def m4 (re-matcher rx1 s2))
#'user/m4
user> (.matches m3)
true
user> (.matches m4)
true
user> (re-groups m4)
["[WARNING]: \tTimezone not set \r\n"
"WARNING"
" \tTimezone not set "]