Почему sed не работает?

У меня есть некоторый HTML, из которого я пытаюсь извлечь ссылки. Прямо сейчас файл похож на это.

website.com/path/to/file/234432517.gif" width="620">
website.com/path/to/file/143743e53.gif" width="620">
website.com/path/to/file/123473232.gif" width="620">
website.com/path/to/file/634132317.gif" width="620">
website.com/path/to/file/432432173.gif" width="620">

Я пытаюсь использовать sed для удаления " width="620"> от всех строк. Вот мой код sed:

sudo sed -i "s/\"\swidth\=\"\d+\"\>//g" output

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

5
задан 21 July 2017 в 12:44

4 ответа

Поскольку Вы используете PCRE (Perl Совместимые Регулярные выражения) синтаксис и sed не понимает, что, это использует Основные регулярные выражения (BRE) по умолчанию. Это не знает ни одного \s ни \d. Вы также выходите из всех видов вещей, которых не должны оставлять (ни один \= ни \> делают что-либо полезное), не выходя из вещей, которых действительно должны оставить (+ просто означает символ + в BRE Вам нужно \+ для "одного или нескольких".

Это должно сделать то, в чем Вы нуждаетесь:

sed 's/" width="[0-9]\+">//g' file

Или, использование Расширенных регулярных выражений:

sed -E 's/"\s*width="[0-9]+">//g' file

Наконец, как правило Вы никогда не используете sed -i без первого тестирования без -i чтобы быть уверенным, это работает или, если Вы делаете, по крайней мере, используйте -i.bak (-i с любым текстом сделает это) создать резервное копирование.

19
ответ дан 23 November 2019 в 08:38

Вот мой sed решение:

sed -E 's/(.*)" width="[0-9]+">/\1/' filename

И как альтернатива sed Я предлагаю использовать grep извлечь данные из файла:

Это работало бы на Вас:

grep -o "website.*\.gif" filename

И как terdon предложенный, вот является взгляд вперед использованием решения grep:

grep -Po '.*(?="\swidth="\d*">)' filename

Также cut хороший вариант в Вашей ситуации:

cut -f1 -d'"' filename
4
ответ дан 23 November 2019 в 08:38

Или поскольку более короткий обмен просто удаляют все после gif

sed 's/gif.*/gif/' file

.* соответствия, которые любое количество любых символов, пока, что Вы хотите проиграть, всегда после строки, которой можно определить местоположение... и что нет никаких других экземпляров его в строке. Это соответствовало бы website.com/path/to/gif/xyz.gif" width..." на ранее gif, поэтому дайте нежелательные результаты.

1
ответ дан 23 November 2019 в 08:38

Так как Вы записали регулярное выражение Perl, можно просто использовать Perl. Можно выпустить короткое perl команда вместо a sed команда. Затем Вы не должны переводить свое регулярное выражение на другой диалект, и Вы не должны воздерживаться ни от одной из удобных функций Perl.

  • Вместо sed -i, использовать perl -pi -e.
  • Вместо sed -i.bak, использовать perl -pi.bak -e. (Можно использовать любой суффикс, это не должно быть .bak.)

Поскольку terdon говорит, с -i лучше указывать суффикс, таким образом, он создает файл резервной копии, по крайней мере, если Вы не попробовали ту же команду без -i сначала. (Это столь же верно с perl как с sed.)

Вот то, на что это похоже с Вашей определенной командой:

perl -pi.bak -e "s/\"\swidth\=\"\d+\"\>//g" file

При использовании одинарных кавычек вокруг поиска и заменяющего шаблона Вы не должны выходить " символы, которые появляются в нем или отслеживают интересные правила оболочки для дважды заключенного в кавычки текста. Это поможет записать и читать. (Это не характерно для perl; Ваш sed команда могла быть так же упрощена.) Эта команда эквивалентна:

perl -pi.bak -e 's/"\swidth\="\d+"\>//g' file

С любой из тех команд строки в Вашем примере изменяются на:

website.com/path/to/file/234432517.gif
website.com/path/to/file/143743e53.gif
website.com/path/to/file/123473232.gif
website.com/path/to/file/634132317.gif
website.com/path/to/file/432432173.gif

Дальнейшее чтение:

0
ответ дан 23 November 2019 в 08:38

Другие вопросы по тегам:

Похожие вопросы: