sed - как удалить все, кроме определенного шаблона? - PullRequest
10 голосов
/ 20 августа 2011

Мне нужно удалить все, кроме 1, 2 или 3 цифр (0-9, или 10-99, или 100) перед % (хотя я не хочу видеть%)из выходных данных другой команды и перенаправьте их к другой команде.Я знаю, что

sed -n '/%/p'

покажет только те строки, которые содержат % , но это не то, что я хочу.Как я могу избавиться от остального нежелательного текста и оставить только эти числа, чтобы затем передать их другой команде?

Ответы [ 6 ]

22 голосов
/ 20 августа 2011

Если вы не полностью привязаны к sed, это именно то, что делает grep -o:

grep -o '[0-9]\{1,3\}%'
2 голосов
/ 21 августа 2011

РЕДАКТИРОВАТЬ : Я неправильно понял ОП и отправил неверный ответ. Я изменил его на ответ, который, как мне кажется, решил бы проблему в более общем сценарии.

Для файла, подобного приведенному ниже:

$ cat input
abc
123%
123
abc%
this is 456% and nothing more
456

Использование sed -n -E 's/(^|.*[^0-9])([0-9]{1,3})%.*/\2/p' input

$  sed  -n -E 's/(^|.*[^0-9])([0-9]{1,3})%.*/\2/p' input
123
456

Флаг -n делает sed для подавления автоматического вывода строк. Затем мы используем флаг -E, который позволит нам использовать расширенные регулярные выражения. (В GNU sed флаг не -E, а вместо -r).

Теперь идет команда s///. Группа (^|.*[^0-9]) соответствует либо началу строки (^), либо серии из нуля или более символов (.*), заканчивающейся нецифровым символом ([^0-9]). [0-9]\{1,3\} просто соответствует от одной до трех цифр и привязывается к группе (разделителями группы ( и )), если группе предшествует (^|.*[^0-9]), за которой следует %. Тогда .* соответствует всему до и после этого шаблона. После этого мы заменяем все на вторую группу (([0-9]{1,3})), используя обратную ссылку \2. Поскольку мы передали -n в sed, ничего не печаталось, но мы передали флаг p команде s///. В результате , если замена выполняется , то полученная строка печатается. Обратите внимание, что p - это флаг из s///, , а не команда p, потому что она приходит сразу после последней /.

0 голосов
/ 28 октября 2013
sed -n "/[0-9]\{1,2\}%/ s/^[^0-9]*\([0-9]\{1,2\}\)%.*/\1/p
/100%/ s/.*/100/p
"

100% должно быть извлечено, потому что в противном случае число типа 987% (или 123%, если отфильтровано по 1 в 1-й позиции) также отправляется на выход

0 голосов
/ 21 августа 2011

Используйте awk вместо sed.

$ cat file
one two 100% three
10% four 1% five

$ awk '{
  for(i=1;i<=NF;i++) 
   if ($i ~/%$/) { print $i+0} }
  'file
100
10
1

Для каждого поля проверьте, есть ли в конце знак %.Если да, выведите номер.($ i + 0 означает преобразование в целое число).Минимальное регулярное выражение.

0 голосов
/ 21 августа 2011

Вот мой снимок:

sed "/^[0-9]{1,3}%$/ bnum; d; :num s/%//"

Если строка состоит из 1-3 цифр, за которыми следует%, она удаляет знак%. В противном случае он удаляет всю строку. Таким образом, для ввода, таких как

adsf
50
52%
 1
 12%
test%
1234%
%%%
85%
bye

Это дает

52
85
0 голосов
/ 20 августа 2011

sed -e 's/[^0-9]*\([0-9]*\)%.*/\1/' захватывает цифры в группе, и поскольку шаблон соответствует всему (начальный и конечный .*), все это отбрасывается.

(мой шаблон соответствует любому количеству цифр, начиная с sedрегулярные выражения не поддерживают удобные ярлыки, такие как [0-9]{1,3}, которые вы видите в perlre и других, поэтому я решил не усложнять, чтобы проиллюстрировать принцип, который вас интересует)

Редактировать: исправить цитирование и заменить ведущий .* с [^0-9]*, чтобы избежать жадного совпадения, потребляющего числа.Еще раз проще с Perlre, где вы можете использовать не жадный .?*

...