Ответ 1
Совместите всю строку, поэтому добавьте .*
в начало вашего регулярного выражения. Это приводит к замене всей строки на содержимое группы
echo "foo bar <foo> bla 1 2 3.4" |
sed -n 's/.*\([0-9][0-9]*[\ \t][0-9.]*[ \t]*$\)/\1/p'
2 3.4
Я хочу взять последние два числа (один 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]*$\)/\1/p'
Как я могу напечатать только часть строки, которая соответствует регулярному выражению в группе?
Совместите всю строку, поэтому добавьте .*
в начало вашего регулярного выражения. Это приводит к замене всей строки на содержимое группы
echo "foo bar <foo> bla 1 2 3.4" |
sed -n 's/.*\([0-9][0-9]*[\ \t][0-9.]*[ \t]*$\)/\1/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 фрагменты исходной строки. Вы также можете указать диапазон в виде списка, например 6,7
.
Я согласен с @kent, что это хорошо подходит для grep -o
. Если вам нужно извлечь группу из шаблона, вы можете сделать это с помощью второго grep.
# To extract \1 from /xx([0-9]+)yy/
$ echo "aa678bb xx123yy xx4yy aa42 aa9bb" | grep -Eo 'xx[0-9]+yy' | grep -Eo '[0-9]+'
123
4
# To extract \1 from /a([0-9]+)b/
$ echo "aa678bb xx123yy xx4yy aa42 aa9bb" | grep -Eo 'a[0-9]+b' | grep -Eo '[0-9]+'
678
9