Regex: как получить слова от строки (C#)

Мой вход состоит из отправленных пользователями строк.

То, что я хочу сделать, создают словарь со словами, и как часто они использовались. Это означает, что я хочу проанализировать строку, удалить весь мусор и получить список слов, как произведено.

Например, скажите, что вход "#@!@LOLOLOL YOU'VE BEEN \***PWN3D*** ! :') !!!1einszwei drei !"

Вывод, в котором я нуждаюсь, является списком:

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

Я не герой в регулярных выражениях и гуглил, но мои швы кун-фу Google, чтобы быть слабым …

Как я пошел бы от входа до требуемого вывода?

13
задан Greg Bacon 11 October 2017 в 19:42
поделиться

5 ответов

Я часто нахожусь в режиме визуального блока ( Ctrl + v ) больше, чем любой из других визуальных режимов.

После получения информации об этом режиме можно легко удалить отступы, комментарии и т.д. По моему опыту, это часто быстрее, чем выяснить, как сформировать эквивалентный оператор search-and-delete.

Вы также можете добавить отступы (или комментарии, как сказал Чериан), выбрав блок текста и нажав I , набрав все, что вы хотите добавить, и нажав Esc (примечание: вам может потребоваться перерисовать экран (например, переместив курсор), чтобы увидеть эффекты этого).

-121--2827348-

Можно переопределить виджет и предоставить словарь tab с набором индексов:

http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.Widget.attrs

-121--3216567-

Simple Regex:

\w +

Это соответствует последовательности символов «word». Это почти то, что вы хотите.

Это несколько точнее:

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

Оно соответствует любому числу символов слова, гарантируя, что первый символ не является цифрой.

Вот мои совпадения:

1 ЛОЛОЛОЛ
2 ВЫ
3 БЫЛО
4 PWN3D
5 einszwei
6 drei

Это больше похоже на это.

EDIT:
Причина отрицательного обзора заключается в том, что некоторые ароматизаторы regex поддерживают символы Юникода. При использовании [a-zA-Z] будет пропущено несколько желательных символов «слова». Разрешение \w и запрет \d включает в себя все символы Юникода, которые могли бы начать слово в любом блоке текста.

EDIT 2:
Я нашел более сжатый способ получить эффект отрицательного lookbehind: Double negative character class с единственным отрицательным исключением.

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

Это то же самое, что и выше, за исключением того, что это также гарантирует, что слово заканчивается символом слова. И, наконец, есть:

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

Обеспечение наличия не более двух несловосочетаний в строке. Она совпадает со словами, но не со словами, что имеет смысл. Если вы хотите, чтобы он соответствовал «word--up», но не «word---up», вы можете изменить 2 на 3 .

19
ответ дан 1 December 2019 в 20:56
поделиться

Вы не обязательно нуждаетесь в регенсе для этого, если токена, это все, что вы делаете. Сначала вы могли бы санировать строку, удалив все не буквенные символы, кроме пробелов, а затем выполнять Split () на пространстве. Это будет работать только для всего, хотя сокращения могут быть жесткими. Это должно заставить вас начаться хотя бы.

2
ответ дан 1 December 2019 в 20:56
поделиться

Мое чувство кишечника не будет использовать регулярные выражения, но просто сделайте петлю или два.

Итайте за каждого символа в строке, если не действительный символ, замените его пространством Затем используйте String.Split () и разделить пробелы.

Эппострофы и дефисы могут быть немного сложнее, чтобы определить, являются ли они нежелательными персонажами или легинными. Но если вы используете для петли для петли, чтобы перейти к строке, то оглядываясь назад и вперед из текущего символа, следует вам помочь.

Тогда у вас будет список слов - для каждого из этих слов, проверьте, действительно ли они в вашем словаре. Если вы хотите, чтобы это было быстрым, выполнение некоторого бинарного поиска будет лучше всего. Но просто чтобы заставить его работать линейный поиск будет легче начать с.

Редактировать: я только упомянул словарную вещь, потому что я подумал, что вам может быть интересно только в законных словах, то есть не «ASDFASDF», но игнорируйте это последнее утверждение, если это не то, что вам нужно.

0
ответ дан 1 December 2019 в 20:56
поделиться

Используя следующую

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 = "#@!@LOLOLOL 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]
2
ответ дан 1 December 2019 в 20:56
поделиться

Вы должны посмотреть в обработку естественных языков (NLP), а не регулярных выражений, и если вы нацеливаетесь на более чем один разговорный язык, вам также необходимо учитывать это. Так как вы используете C #, проверьте проект Sharpnlp .

Редактировать : Этот подход необходимо только если вы заботитесь о семантическом содержании слов, которые вы пытаетесь расстаться.

5
ответ дан 1 December 2019 в 20:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: