Подтвердить что ты не робот

Регулярное выражение, разделите строку заглавной буквой, но игнорируйте TLA

Я использую регулярное выражение

System.Text.RegularExpressions.Regex.Replace(stringToSplit, "([A-Z])", " $1").Trim()

разделять строки заглавной буквой, например:

"MyNameIsSimon" становится "Мое имя - это Симон"

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

"USAToday" станет 'USA Today'

Можно ли это сделать?

EDIT: Спасибо всем за ответ. Возможно, я не мог полностью подумать об этом, в некоторых случаях "A" и "I" нужно было бы игнорировать, но это невозможно (по крайней мере, не в значимом смысле). В моем случае, хотя ответы ниже делают то, что мне нужно. Спасибо!

4b9b3361

Ответ 1

((?<=[a-z])[A-Z]|[A-Z](?=[a-z]))

или его двоюродный брат с поддержкой Unicode

((?<=\p{Ll})\p{Lu}|\p{Lu}(?=\p{Ll}))

если глобально заменить на

" $1"

ручки

TodayILiveInTheUSAWithSimon
USAToday
IAmSOOOBored

получая

 Today I Live In The USA With Simon
USA Today
I Am SOOO Bored

На втором шаге вам придется обрезать строку.

Ответ 2

любой символ верхнего регистра, за которым не следует символ верхнего регистра:

Replace(string, "([A-Z])(?![A-Z])", " $1")

Edit:

Я только заметил, что вы используете это для перечислений. Я действительно не поощряю использование строковых представлений перечислений, подобных этому, и проблемы, стоящие перед вами, являются хорошей причиной. Посмотрите на это вместо этого: http://www.refactoring.com/catalog/replaceTypeCodeWithClass.html

Ответ 3

Вы можете подумать об изменении перечислений; Руководства по кодированию MS предлагают Паскаль обрезать аббревиатуры, как если бы они были словами; XmlDocument, HtmlWriter и т.д. Двухбуквенные акрионимы не следуют этому правилу; System.IO.

Итак, вы должны использовать UsaToday, и ваша проблема исчезнет.

Ответ 4

выражение Томалака работало для меня, но не со встроенной функцией Replace. Regex.Replace(), однако, действительно работал.

For i As Integer = 0 To names.Length - 1
  'Worked
  names(i) = Regex.Replace(names(i), "((?<=[a-z])[A-Z]|[A-Z](?=[a-z]))", " $1").TrimStart()

  ' Didn't work
  'names(i) = Replace(names(i), "([A-Z])(?=[a-z])|(?<=[a-z])([A-Z])", " $1").TrimStart()
Next

Кстати, я использую это, чтобы разделить слова в именах перечислений для отображения в пользовательском интерфейсе и прекрасно работает.

Ответ 5

Примечание. Я недостаточно хорошо читал вопрос, USAToday вернется "Сегодня"; поэтому этот anwser не является правильным.

    public static List<string> SplitOnCamelCase(string text)
    {
        List<string> list = new List<string> ();
        Regex regex = new Regex(@"(\p{Lu}\p{Ll}+)");
        foreach (Match match in regex.Matches(text))
        {
            list.Add (match.Value);
        }
        return list;
    }

Это будет соответствовать "WakeOnBoot" как "Wake On Boot" и ничего не возвращает в NMI или TLA

Ответ 6

Моя версия, которая также обрабатывает простые арифметические выражения:

private string InjectSpaces(string s)
{
    var patterns = new string[] {
        @"(?<=[^A-Z,&])[A-Z]",          // match capital preceded by any non-capital except ampersand
        @"(?<=[A-Z])[A-Z](?=[a-z])",    // match capital preceded by capital and followed by lowercase letter
        @"[\+\-\*\/\=]",                // match arithmetic operators
        @"(?<=[\+\-\*\/\=])[0-9,\(]"    // match 0-9 or open paren preceded by arithmetic operator
    };
    var pattern = $"({string.Join("|", patterns)})";
    return Regex.Replace(s, pattern, " $1");
}