пробег (и) цифр
Этот ответ работает с любым количеством цифр групп. Пример:
$ echo 'Num123that456are7899900contained0018166intext' |
> sed -En 's/[^0-9]*([0-9]{1,})[^0-9]*/\1 /gp'
123 456 7899900 0018166
Расширенный ответ.
Есть ли способ сказать sed выводить только захваченные группы?
Да. заменить весь текст группой захвата:
$ echo 'Number 123 inside text' | sed 's/[^0-9]*\([0-9]\{1,\}\)[^0-9]*/\1/'
123
s/[^0-9]* # several non-digits
\([0-9]\{1,\}\) # followed by one or more digits
[^0-9]* # and followed by more non-digits.
/\1/ # gets replaced only by the digits.
Или с расширенным синтаксисом (меньше обратных кавычек и допускается использование +):
$ echo 'Number 123 in text' | sed -E 's/[^0-9]*([0-9]+)[^0-9]*/\1/'
123
Чтобы не печатать оригинальный текст, когда номер отсутствует, используйте:
$ echo 'Number xxx in text' | sed -En 's/[^0-9]*([0-9]+)[^0-9]*/\1/p'
- (- n) Не печатать ввод по умолчанию.
- (/ p) печатать, только если была произведена замена.
И сопоставить несколько чисел (а также распечатать их):
$ echo 'N 123 in 456 text' | sed -En 's/[^0-9]*([0-9]+)[^0-9]*/\1 /gp'
123 456
Это работает для любого количества запусков цифр:
$ str='Test Num(s) 123 456 7899900 contained as0018166df in text'
$ echo "$str" | sed -En 's/[^0-9]*([0-9]{1,})[^0-9]*/\1 /gp'
123 456 7899900 0018166
Что очень похоже на команду grep:
$ str='Test Num(s) 123 456 7899900 contained as0018166df in text'
$ echo "$str" | grep -Po '\d+'
123
456
7899900
0018166
О \ d
и шаблон: /([\d]+)/
Sed не распознает синтаксис '\ d' (ярлык). Используемый выше эквивалент ascii [0-9]
не совсем эквивалентен. Единственное альтернативное решение - использовать класс символов: '[[: digit:]] `.
Выбранный ответ использует такие «классы символов» для построения решения:
$ str='This is a sample 123 text and some 987 numbers'
$ echo "$str" | sed -rn 's/[^[:digit:]]*([[:digit:]]+)[^[:digit:]]+([[:digit:]]+)[^[:digit:]]*/\1 \2/p'
Это решение работает только для (точно) двух серий цифр.
Конечно, поскольку ответ выполняется внутри оболочки, мы можем определить пару переменных, чтобы сделать такой ответ короче:
$ str='This is a sample 123 text and some 987 numbers'
$ d=[[:digit:]] D=[^[:digit:]]
$ echo "$str" | sed -rn "s/$D*($d+)$D+($d+)$D*/\1 \2/p"
Но, как уже объяснялось, лучше использовать команду s/…/…/gp
:
$ str='This is 75577 a sam33ple 123 text and some 987 numbers'
$ d=[[:digit:]] D=[^[:digit:]]
$ echo "$str" | sed -rn "s/$D*($d+)$D*/\1 /gp"
75577 33 123 987
Это будет охватывать как повторяющиеся серии цифр, так и написание короткой (er) команды.