2010-01-29 17 views
11

我的輸入包含用戶發佈的字符串。正則表達式:如何從字符串中獲取單詞(C#)

我想要做的是創建一個包含單詞的字典,以及它們被多久使用一次。 這意味着我想分析一個字符串,刪除所有的垃圾,並獲得單詞列表作爲輸出。

例如,假設輸入是 "#@[email protected] YOU'VE BEEN \***PWN3D*** ! :') !!!1einszwei drei !"

我需要的輸出列表:

  • "LOLOLOL"
  • "YOU'VE"
  • "BEEN"
  • "PWN3D"
  • "einszwei"
  • "drei"

我不是英雄,在正則表達式,並已谷歌搜索,但我的谷歌,功夫接縫要弱…

我將如何從輸入轉到想要的輸出?

+3

http://regular-expressions.info – Jason 2010-01-29 00:19:13

回答

18

簡單的regex:

\w+

此的 「字」 字符的字符串匹配。那就是差不多你想要什麼。

這是更爲精準:

\w(?<!\d)[\w'-]*

它匹配任意數量的單詞字符,確保第一個字符是不是一個數字。

這裏是我的比賽:

1 LOLOLOL
2你
3中已
4 PWN3D
5 einszwei
6 DREI

現在,這更像它。

編輯:
的原因負查找的背後,是一些正則表達式的味道支持Unicode字符。使用[a-zA-Z]會錯過很多需要的「單詞」字符。允許\w和不允許\d包括所有可能會在任何文本塊中啓動單詞的Unicode字符。

編輯2:
我發現了一個更簡潔的方式來獲得負回顧後的效果:僅用一個負排除雙重否定字符類。

[^\W\d][\w'-]*(?<=\w)

這是與上述相同,不同的是它也確保了字結束與字字符。最後,有:

[^\W\d](\w|[-']{1,2}(?=\w))*

確保有連續不超過兩個非單詞字符。又名,它匹配「單詞」,但不匹配「單詞」,這是有道理的。如果您希望它匹配「單詞向上」,而不是「單詞向上」,則可以將2更改爲3

+0

非常感謝,作品像魅力! :) – Led 2010-01-29 01:07:13

+0

@Led:您可能想在編輯#2結束時查看正則表達式。它可能會更接近你正在尋找的東西。 – 2010-01-29 02:46:09

+0

downvoted。帶'''符號的單詞分爲若干部分 – 2017-10-10 07:38:34

5

你應該看看自然語言處理(NLP),而不是正則表達式,如果你的目標是多種語言,你也需要考慮它。由於您使用的是C#,請查看SharpNLP項目。

編輯:這種方法只有在你關心你試圖拆分的單詞的語義內容時纔是必要的。

+1

謝謝非常多的迴應!:) 但讓我們保持簡單,並說我不在乎語言 - 我只會考慮帶有'''和/或' - '字符的單詞? – Led 2010-01-29 00:21:37

+1

@Mike阿特拉斯,不錯的鏈接。 +1 – Gabe 2010-01-29 00:22:22

+0

如果你不關心語言,那麼爲什麼不只是string.Replace()你不想要的所有字符,然後string.Split()它的空格字符?不需要正則表達式。 – 2010-01-29 00:22:46

2

你不一定需要這樣的正則表達式,如果標記化是你所做的一切。首先,您可以通過除去空格以外的所有非字母字符來清理字符串,然後對空格字符執行Split()。這對大多數情況都適用,雖然收縮可能很艱難。這應該讓你至少開始。

+0

好的,我想要做的是刪除所有無效字符,但'和 - 字符也是無效的,如果它們不在字母之間。 (在「word-up」中 - 是有效的,在「word ----- up」中 - 字符應該被刪除......) – Led 2010-01-29 00:28:46

+0

你可以在那裏放一張支票,看看是否有'''或'-'被字母字符包圍,如果是,則不要刪除。 – Jason 2010-01-29 00:38:11

0

我的直覺並不是使用正則表達式,而只是做一兩個循環。

迭代字符串中的每個字符,如果不是有效字符,則用空格替換它 然後使用String.Split()並拆分空格。

應用程序和連字符可能會更難以確定它們是垃圾字符還是連字符。但是,如果您使用for循環遍歷字符串,則從當前字符開始向前和向後查看應該會對您有所幫助。

然後你會得到一個單詞列表 - 對於這些單詞中的每一個,檢查它們在你的字典中是否有效。如果你希望這樣做很快,那麼執行一些二進制搜索將是最好的。但爲了讓它工作,線性搜索將更容易開始。

編輯:我只提到字典的事情,因爲我認爲你可能只對合法的詞感興趣,即不是「asdfasdf」,但忽略最後一條語句,如果這不是你所需要的。

+0

你不想用空格替換無效字符。 – Jason 2010-01-29 00:41:54

2

使用以下

var pattern = new Regex(
    @"([^\W_\d]    # starting with a letter 
          # followed by a run of either... 
     ([^\W_\d] |   # more letters or 
     [-'\d](?=[^\W_\d]) # ', -, or digit followed by a letter 
    )* 
     [^\W_\d]    # and finishing with a letter 
    )", 
    RegexOptions.IgnorePatternWhitespace); 

var input = "#@[email protected] YOU'VE BEEN *PWN3D* ! :') !!!1einszwei drei foo--bar!"; 

foreach (Match m in pattern.Matches(input)) 
    Console.WriteLine("[{0}]", m.Groups[1].Value); 

產生的

[LOLOLOL] 
[YOU'VE] 
[BEEN] 
[PWN3D] 
[einszwei] 
[drei] 
[foo] 
[bar]
+0

你能否正常寫一個正則表達式?我的意思是沒有多餘字符的單行 – 2017-10-10 07:36:59

+0

好的解釋。 – AnthonyVO 2018-01-23 21:10:45

0

輸出我寫了一個擴展的字符串是這樣的:

private static string[] GetWords(string text) 
    { 
     List<string> lstreturn = new List<string>(); 
     List<string> lst = text.Split(new[] { ' ' }).ToList(); 
     foreach (string str in lst) 
     { 
      if (str.Trim() == "") 
      { 
       lstreturn.Add(str); 
      } 
     } 
     return lstreturn.ToArray(); 
    } 
+0

這似乎不是對我的擴展。你錯過了一個'this'嗎? – 2017-10-28 06:15:23

相關問題