2011-04-20 94 views
2

我需要建立與這些模式匹配的話,一個正則表達式的話:正則表達式來找到分隔字母和數字或不被符號

字母和數字:

A35,35A,B503X,1ABC5

字母和由分隔的數字 「 - 」, 「/」, 「\」:

AB-10,10-AB,A10-BA,BA-A10等等......

我寫這個正則表達式是:

\b[A-Za-z]+(?=[(?<!\-|\\|\/)\d]+)[(?<!\-|\\|\/)\w]+\b|\b[0-9]+(?=[(?<!\-|\\|\/)A-Za-z]+)[(?<!\-|\\|\/)\w]+\b 

它的工作原理部分,但它僅匹配字母或只用符號分隔的數字。 例子:

10-10,開放式辦公室等

而且我不想要這個匹配。

我想我的正則表達式是非常重複的,有點難看。 但這是我現在所擁有的。

任何人都可以幫助我嗎?

我正在使用java/groovy。

在此先感謝。

+0

在未來你可以玩這個工具,它是我的救星:http://regexpal.com/ – 2011-04-20 14:35:27

+0

什麼是你做的,不要有什麼區別不想匹配?每組必須包含字母和數字? – 2011-04-20 14:43:47

+0

在這個字符串中:「10 10-10 open office 10B A10 UCS5000 code DV-3000 300-BR」,正則表達式需要匹配這個詞:「10B,A10,UCS5000,DV-3000,300-BR」。字母和數字在同一個詞中,用符號分隔或不用符號 - ,/,\ – 2011-04-20 14:48:36

回答

6

有趣的挑戰。下面是與挑選出的各類「字」正則表達式的Java程序你是後:

import java.util.regex.*; 
public class TEST { 
    public static void main(String[] args) { 
     String s = "A35, 35A, B503X, 1ABC5 " + 
      "AB-10, 10-AB, A10-BA, BA-A10, etc... " + 
      "10-10, open-office, etc."; 
     Pattern regex = Pattern.compile(
      "# Match special word having one letter and one digit (min).\n" + 
      "\\b      # Match first word having\n" + 
      "(?=[-/\\\\A-Za-z]*[0-9]) # at least one number and\n" + 
      "(?=[-/\\\\0-9]*[A-Za-z]) # at least one letter.\n" + 
      "[A-Za-z0-9]+    # Match first part of word.\n" + 
      "(?:      # Optional extra word parts\n" + 
      " [-/\\\\]    # separated by -,/or //\n" + 
      " [A-Za-z0-9]+   # Match extra word part.\n" + 
      ")*      # Zero or more extra word parts.\n" + 
      "\\b      # Start and end on a word boundary", 
      Pattern.COMMENTS); 
     Matcher regexMatcher = regex.matcher(s); 
     while (regexMatcher.find()) { 
      System.out.print(regexMatcher.group() + ", "); 
     } 
    } 
} 

這裏是正確的輸出:

A35, 35A, B503X, 1ABC5, AB-10, 10-AB, A10-BA, BA-A10,

注意,只有複雜這些「醜陋」的正則表達式是那些沒有正確格式化和評論的!

+0

非常好!這正是我需要的!謝謝ridgerunner! – 2011-04-20 17:24:36

+0

真棒! – jalil 2014-12-01 18:19:19

1

只要使用此:

([a-zA-Z]+[-\/\\]?[0-9]+|[0-9]+[-\/\\]?[a-zA-Z]+) 

在Java \\\/應該進行轉義:

([a-zA-Z]+[-\\\/\\\\]?[0-9]+|[0-9]+[-\\\/\\\\]?[a-zA-Z]+) 
+0

這個正則表達式只會匹配字母或只有數字。 – 2011-04-20 14:41:59

+0

好的,我編輯了我的答案。 – hsz 2011-04-20 14:51:56

+0

這幾乎工作。如果我有這種情況:DV5-500,這個正則表達式只匹配DV5。我會編輯我的問題,以便更清楚地瞭解可能性。 – 2011-04-20 15:00:47

0

我第一次合格率

(^|\s)(?!\d+[-/\\]?\d+(\s|$))(?![A-Z]+[-/\\]?[A-Z]+(\s|$))([A-Z0-9]+[-/\\]?[A-Z0-9]+)(\s|$) 

很抱歉,但它不是Java的格式(你需要編輯\ \ S等)。此外,您不能使用\b b/c字邊界是任何非字母數字和下劃線,因此我使用\s和字符串的開始和結束。

這仍然是一個有點生

編輯

第2版,稍微好一點,但可以爲性能通過全光照的佔有慾量詞得到改善。它匹配ABC76AB-323434-F等,但不ABC19\23

((?<=^)|(?<=\s))(?!\d+[-/\\]?\d+(\s|$))(?![A-Z]+[-/\\]?[A-Z]+(\s|$))([A-Z0-9]+[-/\\]?[A-Z0-9]+)((?=$)|(?=\s)) 
0

的條件(OR NOT A)可以被遺漏。所以符號可以被忽略。

for (String word : "10 10-10 open-office 10B A10 UCS5000 code DV-3000 300-BR".split (" ")) 
    if (word.matches ("(.*[A-Za-z].*[0-9])|(.*[0-9].*[A-Za-z].*)")) 
     // do something 

你沒有提到-X4,4x-,4-X,-4-x或-4-X,我希望他們都來匹配。

我的表達式看起來只是用於某些東西-a-something-digits-something,其中某些東西可能是alpha,數字或符號,反之亦然:something-alpha-something-digits-something。如果可能發生其他情況,例如!#$〜()[] {}等等,它會變得更長。

測試使用Scala:

scala> for (word <- "10 10-10 open-office 10B A10 UCS5000 code DV-3000 300-BR".split (" ") 
    | if word.matches ("(.*[A-Za-z].*[0-9])|(.*[0-9].*[A-Za-z].*)")) yield word   
res89: Array[java.lang.String] = Array(10B, A10, UCS5000, DV-3000, 300-BR) 

稍加修改過濾匹配:

String s = "A35, 35A, B53X, 1AC5, AB-10, 10-AB, A10-BA, BA-A10, etc. -4x, 4x- -4-x- 10-10, oe-oe, etc"; 
Pattern pattern = java.util.regex.Pattern.compile ("\\b([^ ,]*[A-Za-z][^ ,]*[0-9])[^ ,]*|([^ ,]*[0-9][^ ,]*[A-Za-z][^ ,]*)\\b"); 
matcher = pattern.matcher (s); 
while (matcher.find()) { System.out.print (matcher.group() + "|") } 

但我仍然有一個錯誤,我不覺得:

A35|35A|B53X|1AC5|AB-10|10-AB|A10-BA|BA-A10|-4x|4x|-4-x| 

4倍應該是4x-,並且-4-x應該是-4-x-。

+0

這是一個有趣的解決方案,但我不能用空格拆分原始字符串(這是我開發的解決方案的一個規則)。謝謝! – 2011-04-20 17:32:25

+0

分裂只是爲了測試這個例子。你要求'匹配單詞',而不是'提取匹配單詞'。 – 2011-04-20 17:38:48

1

不好意思在Python中編寫我的解決方案,我不知道用Java編寫足夠的Java。

pat = re.compile('(?=(?:([A-Z])|[0-9])' ## This part verifies that 
       '[^ ]*'    ## there are at least one 
       '(?(1)\d|[A-Z]))'  ## letter and one digit. 
       '(' 
       '(?:(?<=[ ,])[A-Z0-9]|\A[A-Z0-9])' # start of second group 
       '[A-Z0-9-/\\\\]*' 
       '[A-Z0-9](?= |\Z|,)'    # end of second group 
       ')', 
       re.IGNORECASE) # this group 2 catches the string 

我的解決辦法捕捉所述第二組中所希望的字符串:((?:(?<={ ,])[A-Z0-9]|\A[A-Z0-9])[A-Z0-9-/\\\\]*[A-Z0-9](?= |\Z|,))

之前它驗證至少一個字母和一個數字至少存在於釣到字符串中的部分:

(?(1)\d|[A-Z])是一個條件的正則表達式,這意味着「如果基團(1)釣到的東西,那麼必須有這裏有一個數字,否則必須有一個字母」

的基團(1)是([A-Z])(?=(?:([A-Z])|[0-9])

(?:([A-Z])|[0-9])是匹配的信(釣到)OR一個數字非捕獲基團,所以它匹配時一封信,該組(1)不是空的

標誌re.IGNORECASE允許處理帶有上下字母的字符串。

在第二組中,我有義務編寫(?:(?<=[ ,])[A-Z0-9]|\A[A-Z0-9]),因爲不允許使用非固定長度的lookbehind斷言。這部分表示一個字符不能是' - '前面是空白或字符串的頭部。

在相反,(?= |\Z[,)手段「後的字符串或逗號或空白」末端。

此正則表達式假設的字符'-''/''\'不能是第一個字符或一個捕獲的字符串中的最後一個。這樣對嗎 ?

import re 

pat = re.compile('(?=(?:([A-Z])|[0-9])' ## (from here) This part verifies that 
       '[^ ]*'     #    there are at least one 
       '(?(1)\d|[A-Z]))'  ## (to here) letter and one digit. 
       '((?:(?<=[ ,])[A-Z0-9]|\A[A-Z0-9])' 
       '[A-Z0-9-/\\\\]*' 
       '[A-Z0-9](?= |\Z|,))', 
       re.IGNORECASE) # this group 2 catches the string 

ch = "ALPHA13 10 ZZ 10-10 U-R open-office ,10B a10 UCS5000 -TR54 code vg4- DV-3000 SEA 300-BR gt4/ui bn\\3K" 

print [ mat.group(2) for mat in pat.finditer(ch) ] 

s = "A35, 35A, B503X,1ABC5 " +\ 
    "AB-10, 10-AB, A10-BA, BA-A10, etc... " +\ 
    "10-10, open-office, etc." 

print [ mat.group(2) for mat in pat.finditer(s) ] 

結果

['ALPHA13', '10B', 'a10', 'UCS5000', 'DV-3000', '300-BR', 'gt4/ui', 'bn\\3K'] 
['A35', '35A', 'B503X', '1ABC5', 'AB-10', '10-AB', 'A10-BA', 'BA-A10'] 
相關問題