經過兩天,開始看得懂/a{3,}?/i
是什麼意思了。
這是一段隨意從網路上抓下來的Regexp
。
寫得很嚴謹,e-mail
網址的狀況都有設想到。
/^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6})$/i
但在某些狀況下與這段是一樣的意思。
/^.+@.+$/
例如:
2.7.3 :020 > reg = /^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6})$/i
2.7.3 :022 > mail = "A123__DD.dsf@gmail.com.taipei"
=> "A123__DD.dsf@gmail.com.taipei"
2.7.3 :023 > mail.match?(reg)
=> true
2.7.3 :024 > reg = /^.+@.+$/
=> /^.+@.+$/
2.7.3 :025 > mail = "A123__DD.dsf@gmail.com.taipei"
=> "A123__DD.dsf@gmail.com.taipei"
2.7.3 :026 > mail.match?(reg)
=> true
/^.+@.+$/
這樣也過了!?先不論夠不夠嚴謹(因為如果我這樣寫連@@@
這樣也能過),重點在於再嚴謹的表達式也要搭配正確的方法使用,如果沒有正確的方法,資料庫內也是只會出現一堆奇奇怪怪的mail
,當然email的涵蓋範圍很大,各種形式的mail
都有可能出現,去驗證e-mail
到底正不正確,不如花時間去查這mail註冊過沒或是否uniq
,或是假設mail
不正確時,怎麼讓註冊不通過或讓用戶修改。
正規表達式用在檢測資料內有無特定資料,會比去規定用戶輸入正不正確時輕鬆,例如密碼要大小寫英文,不可以11111
或123123
這樣。
結論是Regexp
不適合驗證email??!!
/./
:點代表任何字元包含符號,但只有m
模式下可匹配\n
。
/abc/
: 這樣等於要匹配有"abc"的部分。
/[abc]/
: 這樣等於a
or b
or c
。另外特殊字元被[]
包住失去效果,成為單純符號。
2.7.3 :055 > /[$%]/.match("ac%$%")
=> #<MatchData "%">
2.7.3 :056 > "ac%$%".scan(/[$%]/)
=> ["%", "$", "%"]
/[^abc]/
:這樣等於不要a
or b
or c
。
2.7.3 :029 > "applebc".scan(/[^abc]/)
=> ["p", "p", "l", "e"]
/[a-z]/
、/[A-Z]/
: Any single character in the range。/[0-9]/
: Any single number in the range。突然不會講中文...
\w
:英文、數字與底線。\W
:非英文、數字與底線。
2.7.3 :068 > /\w*/.match("apple")
=> #<MatchData "apple">
2.7.3 :069 > /\w/.match("apple")
=> #<MatchData "a">
\d
:數字。\D
:非數字。
\s
:空白字元,包括空白、定位、換行、換頁。 它們 ====> ( \t\r\n\f\v)\S
:非空白字元。
2.7.3 :094 > "You are a\ngood boy".scan(/(\s)/)
=> [[" "], [" "], ["\n"], [" "]]
2.7.3 :095 > "You are a\ngood boy".scan(/(\S)/)
=> [["Y"], ["o"], ["u"], ["a"], ["r"], ["e"], ["a"], ["g"], ["o"], ["o"], ["d"], ["b"], ["o"], ["y"]]
(?=regexp)
:確保後面的資料符合regexp。
2.7.3 :109 > /\w*+@(?=(gmail.com))/.match?("apple@hotmail.com")
=> false
2.7.3 :110 > /\w*+@(?=(gmail.com))/.match?("apple@gmail.com")
=> true
(?!regexp)
:確保後面的資料不符合regexp。
2.7.3 :111 > /\w*+@(?!(gmail.com))/.match?("apple@gmail.com")
=> false
(?<=regexp)
:確保前面的資料符合regexp。
2.7.3 :120 > /\d*(?<=0978)/.match("0978123111")
=> #<MatchData "0978">
2.7.3 :121 > /\d*(?<=0978)/.match?("0978123111")
=> true
2.7.3 :122 > /\d*(?<=0978)/.match?("0968123111")
=> false
(?<!regexp)
:確保前面的資料不符合regexp。
請多愛用令人尊敬且有愛的大神製作的Rubular
:https://rubular.com/
def taiwan_mobile_number(nums)
reg = /\A((\+8869\d{2})|(09\d{2}))+((\d{6})|(\-+\d{3}){2}|(\s+\d{3}){2})\z/
nums.match?(reg)
end
puts taiwan_mobile_number("0954 666 666") #=> true
puts taiwan_mobile_number("0905-999-999") #=> true
puts taiwan_mobile_number("0905999888") #=> true
puts taiwan_mobile_number("+886913-333-333") #=> true
puts taiwan_mobile_number("+886913555666") #=> true
這題其實非常簡單,利用已經有的確定實例,來拼湊出Regexp
。
我把+8869..
與09..
為第一區塊,也可以把+886
跟0
就當第一區塊。-...-...
與\s...\s...
當第二區塊,因為有-
後面就不該有\s
,所以直接都重複兩次。
當然一定有更漂亮寫法,我只是依照資料以及需求來寫。
Regexp
。先不管其中是不是有更好的寫法。
/^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6})$/i
第一個區塊。
(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*
[A-Za-Z0_9]+_+ : 大小寫英文與數字組合,加1或多個_
,_
沒有特殊意思,不需反斜線。
[A-Za-z0-9]+-+ : 大小寫英文與數字組合,加1或多個-
,-
需要反斜線。
[A-Za-z0-9]+.+ : 大小寫英文與數字組合,指定加1或多個.
,\.
代表要真正的.
。
[A-Za-z0-9]+++ : 大小寫英文與數字組合,加1或多個+
。
這四個可能的組合會出現0或多次,所以有一個*
在()
外。
第二區塊。
[A-Za-z0-9]+ #大小寫英文與數字組合出現1或多次。
這個蠻重要的@
前面不可以有.
、_
、@
這些符號。
第三區塊@
,代表一定會有一個@
。
第四區塊。@
後面。
((\w+\-+)|(\w+\.))*
(\w+-+) : 任意非符號包含_
字元加1或多個-
。
(\w+.) : 任意非符號包含_
,可以加真正的.
。
以上組合可以出現0或多次所以()*
。
第五區塊。
\w{1,63}\.[a-zA-Z]{2,6}
任意字元最少1個最多63個,一定有一個.
,接2~6個大小寫英文字母。
雖然這邊似乎怪怪的,e-mail有可能會有複數/(\.[a-zA-Z])*/
,不過沒關係,目的在認識別人寫的Regexp
。
雖然我把正確表達式用三天分享很混,希望有機會能讓自己再次遇到Regexp
不會再那麼陌生。
今天的leetcode10. Regular Expression Matching
題目連結:https://leetcode.com/problems/regular-expression-matching/
題目重點:p是一個實體,將實體變成Regexp
,記得用#{}
。
# @param {String} s
# @param {String} p
# @return {Boolean}
def is_match(s, p)
reg = /(#{p})/
s.match(reg)
s == $1
# s.match(/(#{p})/)
# s == $1
end
2.7.3 :039 > p = "a"
=> "a"
2.7.3 :040 > reg = /(#{p})/
=> /(a)/
2.7.3 :041 > s = "aa"
=> "aa"
2.7.3 :042 > s.match(reg)
=> #<MatchData "a" 1:"a">
2.7.3 :043 > s == $1
=> false
非常Easy
的一題對吧,但這題其實被leetcode
分類為Hard
喔。
當熟悉表達式這些天書符號後,可以再多看看Regexp
裡面的一些方法,對於leetcode
的一些對字串檢查或替換的問題,也是比上面花不了多幾個字就解決了。