Regex: как получить слова из строки (C#)
мой ввод состоит из строк, размещенных пользователем.
то, что я хочу сделать, это создать словарь со словами, и как часто они использовались. Это означает, что я хочу разобрать строку, удалить весь мусор и получить список слов в качестве вывода.
например, скажем, что вход
"#@!@LOLOLOL YOU'VE BEEN ***PWN3D*** ! :') !!!1einszwei drei !"
выход мне нужен список:
"LOLOLOL"
"YOU'VE"
"BEEN"
"PWN3D"
"einszwei"
"drei"
Я не герой в регулярных выражениях и гуглил, но мои швы Google-kungfu должны быть слабыми ...
как мне перейти от ввода к требуемому выходу?
6 ответов
Простое Регулярное Выражение:
\w+
это соответствует строке символов" word". Это почти то, что вы хотите.
это немного точнее:
\w(?<!\d)[\w'-]*
он соответствует любому количеству символов слова, гарантируя, что первый символ не был цифрой.
вот мои матчи:
1 на компьютере
2 ТЫ
3 был
4 PWN3D
Пять einszwei
6 drei
теперь, это больше похоже на это.
EDIT:
Причина негативного внешнего вида заключается в том, что некоторые вкусы регулярных выражений поддерживают символы Юникода. Использование [a-zA-Z] пропустит довольно много символов "word", которые желательно. Позволяя \w
и оставить \d
включает все символы Юникода, которые могли бы предположительно начать слово в любом блоке текста.
EDIT 2:
У меня есть нашел более краткий способ получить эффект отрицательного lookbehind: двойной отрицательный класс символов с одним отрицательным исключением.
[^\W\d][\w'-]*(?<=\w)
это то же самое, что и выше, за исключением того, что он также гарантирует, что слово заканчивается С символом слова. И, наконец, есть:
[^\W\d](\w|[-']{1,2}(?=\w))*
обеспечение того, что в строке не более двух не-слов-символов. Ака, он соответствует "word-up", но не " word-up", в этом есть смысл. Если вы хотите, чтобы он соответствовал "word-up", но не" word---up", вы можете изменить 2
до 3
.
вы должны изучить обработку естественного языка (НЛП), а не регулярные выражения, и если вы ориентируетесь более чем на один разговорный язык, вам также нужно учитывать это. Поскольку вы используете C#, проверьте SharpNLP.
редактировать: этот подход необходим только в том случае, если вы заботитесь о семантическом содержании слов, которые вы пытаетесь разделить.
вам не обязательно нужно регулярное выражение для этого, если токенизация-это все, что вы делаете. Сначала вы можете очистить строку, удалив все символы без букв, кроме пробелов, а затем сделать Split()
на пробел. Это будет работать для большинства всего, хотя схватки могут быть жесткими. По крайней мере, это должно помочь тебе начать.
используя следующие
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]
мое чувство кишки не будет использовать регулярные выражения, а просто сделать цикл или два.
повторите каждый символ в строке, если он не является допустимым, замените его пробелом Затем используйте String.Split () и split над пробелами.
Appostrophes и дефисы могут быть немного сложнее определить, являются ли они нежелательными персонажами или законными. Но если вы используете цикл for для итерации по строке, то взгляд назад и вперед от текущего символа должен помочь тебе.
тогда у вас будет список слов - для каждого из этих слов проверьте, являются ли они действительными в вашем словаре. Если вы хотите, чтобы это было быстро, выполнение somekind двоичного поиска было бы лучшим. Но чтобы заставить его работать, проще было бы начать с линейного поиска.
EDIT: я упомянул только словарь, потому что думал, что вас могут интересовать только законные слова, т. е. не "asdfasdf", но игнорировать это последнее утверждение, если это не то, что вы необходимость.
Я написал расширение для строки вроде этого:
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();
}