簡體   English   中英

正則表達式用符號分隔或不分隔字母和數字的單詞

[英]Regex to find words with letters and numbers separated or not by symbols

我需要構建一個與這些模式匹配的正則表達式:

字母和數字:

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。

提前致謝。

有趣的挑戰。 這是一個帶有正則表達式的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,

請注意,唯一復雜的“丑陋”正則表達式是那些沒有正確格式化和評論的正則表達式!

只要用這個:

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

在Java \\\\\\/應該被轉義:

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

請原諒我用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|[AZ])是一個條件正則表達式,意思是“如果組(1)捕獲了某些東西,那么這里必須有一個數字,否則必須有一個字母”

組(1)是([AZ]) in (?=(?:([AZ])|[0-9])

(?:([AZ])|[0-9])是一個非捕獲組,它匹配一個字母(catched)或一個數字,所以當它匹配一個字母時,該組(1)不是空的

標志re.IGNORECASE允許處理帶有大寫或小寫字母的字符串。

在第二組中,我不得不寫(?:(?<=[ ,])[A-Z0-9]|\\A[A-Z0-9])因為不允許具有非固定長度的后向斷言。 此部分表示一個字符不能為“ - ”,前面是空格或字符串的頭部。

相反, (?= |\\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']

我的第一次傳球得分

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

對不起,但它不是java格式化的(你需要編輯\\ \\ s等)。 另外,你不能使用\\b b / ca字邊界是任何不是字母數字和下划線的東西,所以我用\\s和字符串的開頭和結尾。

這仍然有點原始

編輯

版本2略勝一籌,但可以通過占有量詞來改進性能。 它符合ABC76 AB-32 3434-F等,但不符合ABC19\\23等。

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

可以省略條件(A 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-,我希望它們都匹配。

我的表達看起來只是某些東西-α-something-digits-something,其中某些東西可能是alpha,數字或符號,而相反的東西:some-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|

4x應為4x-,-4-x應為-4-x-。

暫無
暫無

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

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