簡體   English   中英

匹配ruby中的正則表達式

[英]match regular expression in ruby

我有如下字符串

201-Grandview-Dr_Early_TX_76802/50-Washington-St

我正在寫一個正則表達式來匹配兩個字符串。

((/^([0-9]+)-([^_]+)-([A-Za-z]{1,})$/ =~ data ) == 0)

但是上面的正則表達式僅匹配50-Washington-St ,而不匹配第二個。

那么,此正則表達式可能有什么問題呢?

匹配的字符串的更新列表:

201-Grandview-Dr_Early_TX_76802
/50-Washington-St
49220-Sunrose-Ln_Palm-Desert_CA_92260
201-Grandview-Dr_Early_TX_76802
50-Washington-St

您可以像這樣修復正則表達式

/^\/?([0-9]+)-(.+?)-(\w+)$/

或匹配整個字符串 (注意^匹配Ruby regex中的行首$行尾):

/\A\/?([0-9]+)-(.+?)-(\w+)\z/

參見Rubular演示

圖案細節

  • \\A字符串開始
  • \\/? -可選的/
  • ([0-9]+) -組1:一位或多位數字
  • -連字符
  • (.+?) -組2:一個或多個除換行符以外的其他字符
  • -連字符
  • (\\w+) -第3組:一個或多個單詞( [A-Za-z0-9_] )字符
  • \\z字符串結尾。

我想提出一種解決此類問題的方法。 主要的收獲是,可以以與其他Ruby代碼相同的方式構造復雜的正則表達式:創建可以輕松測試的小型代碼模塊,然后將這些模塊組合在一起。

考慮必須與正則表達式匹配的第一個字符串。

s = "201-Grandview-Dr_Early_TX_76802"

由於此字符串不包含需要轉義的字符,因此我們可以創建一個正則表達式,使其與該字符串完全匹配,只需將雙引號替換為正斜杠並添加字符串開頭( \\A )和字符串結尾即可( \\z )錨點:

r = /\A201-Grandview-Dr_Early_TX_76802\z/
  #=> /\A201-Grandview-Dr_Early_TX_76802\z/ 
s =~ r
  #=> 0 

這就是我們所擁有的:

/\A201-Grandview\-Dr_Early_TX_76802\z/
   ⬆︎street number
          ⬆︎street name
                  ⬆︎street name suffix
                      ⬆︎city
                           ⬆︎state
                                ⬆︎zip

假定且僅當字符串包含這六個字段中每個字段的允許值並且在相鄰字段之間顯示格式時,正則表達式才應該與字符串匹配。

首先,為六個字段中的每個字段指定一個單獨的正則表達式。 自然,可能需要修改所有這些正則表達式以適應要求。

街道號碼

典型的街道號碼可能是“ 221”,“ 221B”,“ 221b”。 假設我們也可能有“ A19”或“ 221BZ”,但沒有“ 221-B”。 然后我們可以寫:

number = /[[:alnum:]]+/

(在Regexp中搜索“ POSIX”。)

街道名稱

我假設街道名稱由一個單詞或多個單詞組成,並用一個空格隔開,其中每個單詞都是小寫字母,但首字母大寫。

street = /[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*/

/[[:upper:]][[:lower:]]+匹配第一個單詞, (?:\\s[[:upper:]][[:lower:]])*匹配一個空格,后跟一個大寫單詞,重復零次或多次( (?:...)是一個非捕獲組。結尾的*表示重復零次或多次。)

街道名稱后綴

我假設街道名稱的后綴(例如,“ Street”,“ St。”)是一個單詞,除了第一個字符(大寫)以外的所有小寫字母,可以選擇以句點結尾:

suffix = /[[:upper:]][[:lower:]]+\.?/

我假設城市名稱與街道名稱具有相同的要求:

city = street
  #=> /[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*/

州以兩個大寫字母表示:

state = /[[:upper:]]{2}/

我們可以這樣寫:

state = Regexp.union %w| AL AK AZ ... |

但是每當一個領土成為一個新州或(可能是由於最近的事件)一個州脫離聯邦時,我們就必須對其進行更新。

郵政編碼

郵政編碼是五位數或九位數,在前四位數后帶有破折號或連字符。

zip = /\d{5}(?:-\d{4})?/

使用

/\A201-Grandview-Dr_Early_TX_76802\z/

作為我們的模式,因此我們的整體正則表達式如下:

r1 = /
     \A # match start of string 
     #{number}
     -
     #{street}
     -
     #{suffix}
     _
     #{city}
     _
     #{state}
     _
     #{zip}
     \z # match end of string
     /x # free-spacing regex definition mode
  #=> /
  #   \A # match start of string 
  #   /(?-mix:[[:alnum:]]+)
  #   -
  #   (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*)
  #   -
  #   (?-mix:[[:upper:]][[:lower:]]+\.?)
  #   _
  #   (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*)
  #   _
  #   (?-mix:[[:upper:]]{2})
  #   _
  #   (?-mix:\d{5}(?:-\d{4})?)
  #   \z # match start of string 
  /x 

讓我們嘗試第一個字符串及其變體:

"201-Grandview-Dr_Early_TX_76802" =~ r1
   #=> 0
"221B-Grand View-Dr._El Paso_TX_76802-0000" =~ r1
   #=> 0
"2A0B1-Grandview-Dr_Early_ZZ_76802" =~ r1
   #=> 0
"201-GrandView-Dr_Early_TX_76802" =~ r1
   #=> nil
"201-Grandview-Dr_Early_TX_7680" =~ r1
   #=> nil
"201-Pi11ar-St_Early_TX_76802" =~ r1
   #=> nil
"I live at 201-Grandview-Dr_Early_TX_76802" =~ r1
   #=> nil
"201-😎mg Circle-Lane_Early_TX_76802" =~ r1
   #=> nil

現在考慮應該匹配的第二個示例字符串:

"/50-Washington-St"

我們看到正則表達式很簡單

r2 = /
     \A
     \/
     #{number}
     -
     #{street}
     -
     #{suffix}
     \z
     /x
 #=> /
 #   \A
 #   \/
 #   (?-mix:[[:alnum:]]+)
 #   -
 #   (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*)
 #   -
 #   (?-mix:[[:upper:]][[:lower:]]+\.?)
 #   \z
 #   /x 

讓我們嘗試一下。

 "/50-Washington-St" =~ r2
   #=> 0
 "50-Washington-St" =~ r2
   #=> nil
 "/50-Washington-St_Early" =~ r2
   #=> nil

所以現在我們的整體正則表達式很簡單

r = Regexp.union(r1,r2)
  #=> /(?x-mi:
  #   \A # match start of string 
  #   (?-mix:[[:alnum:]]+)
  #   -
  #   (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*)
  #   -
  #   (?-mix:[[:upper:]][[:lower:]]+\.?)
  #   _
  #   (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*)
  #   _
  #   (?-mix:[[:upper:]]{2})
  #   _
  #   (?-mix:\d{5}(?:-\d{4})?)
  #   \z # match end of string
  #   )|(?x-mi:
  #   \A
  #   \/
  #   (?-mix:[[:alnum:]]+)
  #   -
  #   (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*)
  #   -
  #   (?-mix:[[:upper:]][[:lower:]]+\.?)
  #   \z
  #   )/ 

"201-Grandview-Dr_Early_TX_76802" =~ r
  #=> 0
"/50-Washington-St" =~ r
  #=> 0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM