Извлечение чисел из строки с помощью sed и регулярные выражения

еще один вопрос для экспертов sed.

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

./pentaray_run2/Trace_220560.dat

мне нужно извлечь второе из этих чисел-то есть 220560

Я (с некоторой помощью форумов) смог извлечь все номера вместе (т. е. 2220560) с:

sed "s/[^0-9]//g"

или извлечь только первое число с:

sed -r 's|^([^.]+).*$||; s|^[^0-9]*([0-9]+).*$||'

но мне нужен второй номер!! Любая помощь очень ценится.

PS номер, который я ищу, всегда является вторым номером в строке.

4 ответов


это нормально?

sed -r 's/.*_([0-9]*)\..*//g'

С вас пример:

kent$   echo "./pentaray_run2/Trace_220560.dat"|sed -r 's/.*_([0-9]*)\..*//g'
220560

если grep приветствуется :

$ echo './pentaray_run2/Trace_220560.dat' | grep -oP '\d+\D+\K\d+'
220560

и более портативный с Perl С тем же регулярным выражением :

echo './pentaray_run2/Trace_220560.dat' | perl -lne 'print $& if /\d+\D+\K\d+/'
220560

Я думаю, что подход чище и надежнее, чем использование sed


вы можете извлечь последние числа с помощью этого:

sed -e 's/.*[^0-9]\([0-9]\+\)[^0-9]*$//'

легче думать об этом задом наперед:

  1. в конце строки сопоставьте ноль или более символов без цифр
  2. матч (и захват) один или несколько символов цифр
  3. матч по крайней мере один не-значный символ
  4. сопоставьте все символы с началом строки

Часть 3 матча, где происходит" магия", но это также ограничивает ваши матчи должны иметь по крайней мере не цифру перед номером (т. е. вы не можете сопоставить строку только с одним числом, которое находится в начале строки, хотя есть простой обходной путь вставки не цифры в начало строки).

магия состоит в том, чтобы противодействовать жадности слева направо .* (часть 4). Без части 3 Часть 4 потребляла бы все, что может, включая числа, но с ней сопоставление гарантирует, что оно остановится, чтобы позволить по крайней мере не-цифра следовать цифрой, котор нужно уничтожить частями 1 и 2, позволяющ номеру быть захваченным.


Это может сработать для вас (GNU sed):

sed -r 's/([^0-9]*([0-9]*)){2}.*//' file

это извлекает второе число:

sed -r 's/([^0-9]*([0-9]*)){1}.*//' file

и это извлекает первый.