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

8

Итак, у меня есть строка:

ID: 54376

Можете ли вы помочь мне сделать регулярное выражение, которое будет возвращать только числа без "ID:"?

ПРИМЕЧАНИЕ. Эта строка находится в файле.

Блейк Гиббс
источник

Ответы:

14

Попробуй это:

grep -oP '(?<=ID: )[0-9]+' file

или:

perl -nle 'print $1 if /ID:.*?(\d+)/' file
cuonglm
источник
Спасибо за ответ, но мне не нужны все числа из файла, нужен только номер, который появляется после ID:
Блейк Гиббс
Обновил мой ответ.
Cuonglm
1
Обратите внимание, что -oи -Pявляются расширениями GNU для grep. -oработает и на BSD. Поддержка PCRE с -Pне всегда компилируется.
Мэтт
4

Используйте egrepс -oили grepс -Eoопцией, чтобы получить только соответствующий сегмент. Используйте в [0-9]качестве регулярного выражения, чтобы получить только цифры:

grep -Eo [0-9]+ filename
Рохит Джайн
источник
1
OP должен соответствовать только после определенной строки. Смотрите название вопроса.
Тердон
4

Есть много способов сделать это. Например:

  1. Используйте GNU grepс последними PCRE и сопоставьте числа после ID::

    grep -oP 'ID:\s*\K\d+' file
    
  2. Используйте awkи просто напечатайте последнее поле всех строк, начинающихся сID:

    awk '/^ID:/{print $NF}' file
    

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

    awk '($1=="ID:" && $2~/^[0-9]+$/){print $2}' file
    
  3. Используйте GNU grep с расширенными регулярными выражениями и проанализируйте его дважды:

    grep -Eo '^ID: *[0-9]+' file | grep -o '[0-9]*'
    
Тердон
источник
Спасибо! Что \Kделает в первом примере?
rnd_d
2
@rnd_d - это конструкция регулярных выражений, совместимая с Perl (PCRE), которая означает «игнорировать все, что соответствует этой точке». Он используется как вид сзади, он позволяет мне -oпечатать только совпадающую часть, а также отбрасывать вещи, которые мне не интересны. Сравнить echo "foobar" | grep -oP "foobar"иecho "foobar" | grep -oP 'foo\Kbar'
terdon
4
sed -n '/ID: 54376/,${s/[^ 0-9]*//g;/./p}'

Это будет печатать только все числа и пробелы, встречающиеся после ID: 54376в любом файле ввода.

Я только что немного обновил вышеперечисленное, чтобы сделать его немного быстрее *и не pнабирать пустые строки после удаления не числовых символов.

В нем рассматриваются строки из регулярных выражений /ID: 54376/ ,через $последний и на них s///удаляет все или любые *символы , ^не [^ 0-9]*то prints /любую /строку, содержащую .символ остальные.

DEMO:

{
echo line 
printf 'ID: 54376\nno_nums_or_spaces\n'
printf '%s @nd 0th3r char@cter$ %s\n' $(seq 10)
echo 'ID: 54376'
} | sed -n '/ID 54376/,${s/[^ 0-9]*//g;/./p}'

ВЫВОД:

 54376
1  03  2
3  03  4
5  03  6
7  03  8
9  03  10
 54376
mikeserv
источник
1

Используя sed:

{
    echo "ID: 1"
    echo "Line doesn't start with ID: "
    echo "ID: Non-numbers"
    echo "ID: 4"
} | sed -n '/^ID: [0-9][0-9]*$/s/ID: //p'

Это -n«ничего не печатать по умолчанию», /^ID: [0-9][0-9]*$/это «для строк, соответствующих этому регулярному выражению» (начинается с «ID:», затем 1 или более цифр, затем конец строки), и s/ID: //pимеет форму s/pattern/repl/flags- sозначает, что мы Вы делаете замену, чтобы заменить шаблон "ID: "заменяющим текстом ""(пустой строкой), используя pфлаг, который означает «напечатать эту строку после выполнения замены».

Вывод:

1
4
godlygeek
источник
Это не будет работать, если идентификатор присутствует в центре строки.
Авинаш Радж
И не должен, исходя из моего прочтения вопроса. Отсутствие преждевременной обработки этого случая делает код более простым и переносимым.
Godlygeek
0

Еще одна команда GNU sed,

sed -nr '/ID: [0-9]+/ s/.*ID: +([0-9]+).*/\1/p' file

Он печатает любое число после ID:

Авинаш Радж
источник
Вам действительно не нужно +. Если разница между один символов и 3 -х символов ваш скрипт не может работать во всех sedс , которые вы , вероятно , следует сделать следующее : sed -n '/ID: \([0-9][0-9]*\).*/{s//\1/;s/.*[^0-9]//;/./p}'. Ваш ответ также пропускает первый ID: [0-9]в строке, содержащей два вхождения ID: [0-9].
mikeserv
0

Используйте grep + awk:

  grep "^ID" your_file | awk {'print $2'}

Бонус: легко читается :)

Лили
источник
1
Вам не нужно, grepесли вы используете awk. awk '/^ID/ { print $2 }'делает то же самое и избегает проблем с буферизацией строки grep . Это также похоже на одно из решений в ответе @ terdon.
cas