Замена Sed не делает то, что я хочу, и думаю, что должно - PullRequest
1 голос
/ 01 апреля 2010

Я пытаюсь использовать sed, чтобы получить некоторую информацию, которая закодирована в пути к файлу, который передается в качестве параметра моему сценарию (Bourne sh, если это имеет значение). Из этого примера пути я хотел бы, чтобы результат был 8

PATH=/foo/bar/baz/1-1.8/sing/song

Впервые я закрыл регулярное выражение, используя sed в качестве grep:

echo $PATH | sed -n -e  "/^.*\/1-1\.\([0-9][0-9]*\).*/p"

Это правильно распознало строку, поэтому я отредактировал ее для подстановки:

echo $PATH | sed -n -e "s/^.*\/1-1\.\([0-9][0-9]*\).*/\1/"

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

(редактировать)

В примере пути компоненты, отличные от числового, могут содержать числа, похожие на числовой компонент пути, который я перечислил, но не совсем то же самое. Я пытаюсь точно соответствовать компоненту, который является 1-1. и посмотрим, что такое некое число.

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

Ответы [ 5 ]

2 голосов
/ 01 апреля 2010

Опция -n для sed подавляет нормальный вывод, и, поскольку ваша вторая строка не имеет команды p, ничего не выводится. Избавьтесь от -n или наклейте p обратно на конец

1 голос
/ 02 апреля 2010

не используйте PATH в качестве переменной. Это конфликтует с переменной окружения PATH

echo $path|sed -e's/.*1-1\.//;s/\/.*//'
1 голос
/ 01 апреля 2010

Вы можете сократить свою команду, используя + (один или несколько) вместо * (ноль или более):

sed -n -e "s/^.*\/1-1\.\([0-9]\+\).*/\1/"
1 голос
/ 01 апреля 2010

Похоже, вы пытаетесь получить 8 из 1-1.8 (где 8 - любая последовательность чисел), да? Если это так, я бы просто использовал:

echo /foo/bar/baz/1-1.8/sing/song | sed -e  "s/.*\/1-1\.//" -e "s/[^0-9].*//"

Без сомнения, вы можете заставить его работать с одной sed «инструкцией» (-e), но иногда проще просто разбить ее на части.

Первый удаляет все от начала до * включительно 1-1., второй - от первого нечислового после этого до конца.

$ echo /foo/bar/baz/1-1.8/sing/song | sed -e  "s/.*\/1-1\.//" -e "s/[^0-9].*//"
8
$ echo /foo/bar/baz/1-1.752/sing/song | sed -e  "s/.*\/1-1\.//" -e "s/[^0-9].*//"
752

И, кроме того, на самом деле это как Я отлаживаю sed регулярные выражения. Я помещаю простые в независимые инструкции (или независимую часть конвейера для других команд фильтрации), чтобы видеть, что делает каждая из них.


После вашего редактирования это также работает:

$ echo /foo/bar/baz/1-1.962/sing/song | sed -e  "s/.*\/1-1\.\([0-9][0-9]*\).*/\1/"
962

Что касается вашего комментария:

В примере пути компоненты, отличные от числового, могут содержать числа, похожие на числовой компонент пути, который я перечислил, но не совсем то же самое. Я пытаюсь точно соответствовать компоненту, который является 1-1. и посмотрим, что такое некое число.

Команда из двух частей sed, которую я вам дал, должна работать с цифрами в любом месте строки (до тех пор, пока после не найдется 1-1. интересующей вас). Это потому, что он на самом деле удаляет до конкретной строки 1-1. и затем из первой нечисловой). Если у вас есть примеры, которые не работают должным образом, добавьте их в вопрос в качестве обновления, и я исправлю ответ.

0 голосов
/ 19 апреля 2010

Вам не нужно делить ваши паттерны на / (s / a / b / g), но вы можете выбрать каждый символ, поэтому, если вы имеете дело с путями, # более полезен чем /:

echo /foo/1-1.962/sing | sed -e  "s#.*/1-1\.\([0-9]\+\).*#\1#"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...