Regex, который соответствует чему-либо до определенного символа? - PullRequest
1 голос
/ 03 июня 2009

Я должен проанализировать кучу статистических данных из текста, и они все отформатированы как числа.

Например, этот абзац:

В общей сложности 81,8 процента из Нью-Йорка Городские ученики в 3-8 классах встреча или превышение уровня математики стандарты, по сравнению с 88,9 процента студенты в остальной части штата.

Я хочу сопоставить только цифры 81 и 88, а не «.8» и «.9», которые следуют.

Как я могу это сделать? Я слышал термин «обратная ссылка» или «упреждения» или что-то в этом роде Поможет ли что-нибудь из этого?

Я использую C #.

Edit: Требуется, чтобы я получил «3» и «8» в приведенном выше примере. Это простой пример, но мне нужны почти все числа.

Ответы [ 8 ]

3 голосов
/ 03 июня 2009
/[^.](\d+)[^.]/

Как указано ниже, просто используйте MatchObj.Groups (1), чтобы получить цифру.

2 голосов
/ 04 июня 2009

Полное решение C #:

/// <summary>
/// Use of named backrefence 'roundedDigit' and word boundary '\b' for ease of
/// understanding
/// Adds the rounded percents to the roundedPercents list
/// Will work for any percent value
/// Will work for any number of percent values in the string
/// Will also give those numbers that are not in percentage (decimal) format
/// </summary>
/// <returns>true if success, false otherwise</returns>
public static bool TryGetRoundedPercents(string digitSequence, out List<string> roundedPercents)
{
    roundedPercents = null;
    string pattern = @"(?<roundedDigit>\b\d{1,3})(\.\d{1,2}){0,1}\b";

    if (Regex.IsMatch(digitSequence, pattern))
    {
        roundedPercents = new List<string>();
        Regex r = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture);

        for (Match m = r.Match(digitSequence); m.Success; m = m.NextMatch())
            roundedPercents.Add(m.Groups["roundedDigit"].Value);

        return true;
    }
    else
        return false;
}

Из вашего примера возвращается 81, 3, 8 и 88

2 голосов
/ 03 июня 2009

Если вы не хотите иметь дело с группами, вы можете использовать взгляд, как вы говорите; этот шаблон находит целую часть всех десятичных чисел в строке:

Regex integers = new Regex(@"\d+(?=\.\d)");
MatchCollection matches = integers.Matches(str);

matches будет содержать 81 и 88. Если вы хотите сопоставить целую часть ЛЮБОГО числа (десятичное или нет), вы можете вместо этого искать целые числа, которые не начинаются с .:

Regex integers = new Regex(@"(?<!\.)\d+");

На этот раз совпадения будут содержать 81, 3, 8 и 88.

1 голос
/ 03 июня 2009
[^.](\d+)

В вашем примере это будет соответствовать "81", "3", "8", "88"

Вы получите дополнительный символ, прежде чем получите свой номер, но вы можете просто вырезать его в своем коде.

1 голос
/ 03 июня 2009

Попробуйте:

[0-9]*(?=[3])

Он использует предпросмотр для сопоставления только чисел, за которыми следует десятичная точка.

C # код:

Regex regex = new Regex("[0-9]+(?=[.])");
MatchCollection matches = regex.Matches(input);
0 голосов
/ 04 июня 2009

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

$ echo "A total of 81.8 percent of New York City students in grades 3 to 8 are meeting or exceeding grade-level math standards, compared to 88.9 percent of students in the rest of the State." \
| fmt -w 1 | sed -n -e '/^[0-9]/p' | sed -e 's,[^0-9].*,,' | fmt -w 72
81 3 8 88

Первая команда fmt просит следующие команды рассмотреть каждое слово отдельно. Команда «sed -n» выводит только те слова, которые начинаются хотя бы с одного числа. Вторая команда sed удаляет первый нецифровый символ в слове и все после. Вторая команда fmt объединяет все обратно в одну строку.

$ echo "This tests notation like 6.022e+23 and 10e100 and 1e+100." \
| fmt -w 1 | sed -n -e '/^[0-9]/p' | sed -e 's,[^0-9].*,,' | fmt -w 72
6 10 1
0 голосов
/ 03 июня 2009

Попробуйте использовать /(\d+)((\.\d+)?)/

Это в основном означает совпадение последовательности цифр и необязательного десятичного знака с другой последовательностью цифр. Затем используйте MatchObj.Groups(1) для первого значения совпадения, игнорируя второе.

0 голосов
/ 03 июня 2009
/(\d+)\.\d/g

Это будет соответствовать любому числу, за которым следует десятичная дробь (что, я думаю, то, что вы хотите), но будет захватывать только цифры до десятичной дроби. \d будет захватывать только числа (такие же, как [0-9]), поэтому это довольно просто.

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

Edit2: Извините, исправил это так, что он будет игнорировать все десятичные разряды.

/(\d+)(?:\.\d+)?/g
...