Мой вход состоит из отправленных пользователями строк.
То, что я хочу сделать, создают словарь со словами, и как часто они использовались. Это означает, что я хочу проанализировать строку, удалить весь мусор и получить список слов, как произведено.
Например, скажите, что вход "#@!@LOLOLOL YOU'VE BEEN \***PWN3D*** ! :') !!!1einszwei drei !"
Вывод, в котором я нуждаюсь, является списком:
"LOLOLOL"
"YOU'VE"
"BEEN"
"PWN3D"
"einszwei"
"drei"
Я не герой в регулярных выражениях и гуглил, но мои швы кун-фу Google, чтобы быть слабым …
Как я пошел бы от входа до требуемого вывода?
Я часто нахожусь в режиме визуального блока ( 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
.
Вы не обязательно нуждаетесь в регенсе для этого, если токена, это все, что вы делаете. Сначала вы могли бы санировать строку, удалив все не буквенные символы, кроме пробелов, а затем выполнять Split ()
на пространстве. Это будет работать только для всего, хотя сокращения могут быть жесткими. Это должно заставить вас начаться хотя бы.
Мое чувство кишечника не будет использовать регулярные выражения, но просто сделайте петлю или два.
Итайте за каждого символа в строке, если не действительный символ, замените его пространством Затем используйте String.Split () и разделить пробелы.
Эппострофы и дефисы могут быть немного сложнее, чтобы определить, являются ли они нежелательными персонажами или легинными. Но если вы используете для петли для петли, чтобы перейти к строке, то оглядываясь назад и вперед из текущего символа, следует вам помочь.
Тогда у вас будет список слов - для каждого из этих слов, проверьте, действительно ли они в вашем словаре. Если вы хотите, чтобы это было быстрым, выполнение некоторого бинарного поиска будет лучше всего. Но просто чтобы заставить его работать линейный поиск будет легче начать с.
Редактировать: я только упомянул словарную вещь, потому что я подумал, что вам может быть интересно только в законных словах, то есть не «ASDFASDF», но игнорируйте это последнее утверждение, если это не то, что вам нужно.
Используя следующую
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]
Вы должны посмотреть в обработку естественных языков (NLP), а не регулярных выражений, и если вы нацеливаетесь на более чем один разговорный язык, вам также необходимо учитывать это. Так как вы используете C #, проверьте проект Sharpnlp .
Редактировать : Этот подход необходимо только если вы заботитесь о семантическом содержании слов, которые вы пытаетесь расстаться.