sed: печать только соответствующей группы


Я хочу захватить последние два числа (один int, один float; затем необязательные пробелы) и распечатать только их.

пример:

foo bar <foo> bla 1 2 3.4

надо напечатать:

2 3.4

пока у меня есть следующие:

sed -n  's/([0-9][0-9]*[ t][0-9.]*[ t]*$)/replacement/p' 

даст мне

foo bar <foo> bla 1 replacement

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

sed -n  's/([0-9][0-9]*[ t][0-9.]*[ t]*$)//p' 

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

4 88

4 ответа:

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

echo "foo bar <foo> bla 1 2 3.4" |
 sed -n  's/.*\([0-9][0-9]*[\ \t][0-9.]*[ \t]*$\)//p'
2 3.4

grep - это правильный инструмент для извлечения.

используя Ваш пример и ваше регулярное выражение:

kent$  echo 'foo bar <foo> bla 1 2 3.4'|grep -o '[0-9][0-9]*[\ \t][0-9.]*[\ \t]*$'
2 3.4

и для еще одного варианта, я бы пошел с awk!

echo "foo bar <foo> bla 1 2 3.4" | awk '{ print $(NF-1), $NF; }'

это разделит вход (я использую STDIN здесь, но ваш вход может легко быть файлом) на пробелы, а затем распечатать последнее поле, а затем последнее поле. Элемент $NF переменные содержат количество полей, найденных после взрыва на пробелах.

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

команда cut предназначена именно для этой ситуации. Он будет "вырезать" на любом разделителе, а затем вы можете указать, какие куски должны быть выведены.

например: echo "foo bar <foo> bla 1 2 3.4" | cut -d " " -f 6-7

приведет к выходу: 2 3.4

- d устанавливает разделитель

- f выбирает диапазон "полей" для вывода, в этом случае это 6-й по 7-й куски исходной строки.