Почему 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

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

4
задан 21 July 2017 в 22:44

12 ответов

Поскольку вы используете синтаксис PCRE (Perl Compatible Regular Expressions), а sed не понимает этого, он использует Basic Regular Expressions (BRE) по умолчанию. Он не знает ни \s, ни \d. Вы также избегаете всевозможных вещей, которые не должны быть экранированы (ни \=, ни \> ничего полезного не делают], не избегая тем, что нужно экранировать (+ просто означает символ + в BRE, вам нужно \+ для «одного или нескольких».

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

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

Или, используя расширенные регулярные выражения: [ ! d2]

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

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

17
ответ дан 22 May 2018 в 20:20
  • 1
    Вообще говоря, если у вас есть выбор для этих вещей, используйте Perl, поскольку он имеет один из самых мощных движков регулярных выражений, доступных в инструменте командной строки. – Thorbjørn Ravn Andersen 22 July 2017 в 10:25
  • 2
    О, я не знал, что существуют разные языки регулярных выражений. Я только что заполнил свои данные в regexer.com, составленном RegEx и предположил, что это сработает. Благодарю. – Andrew Pullins 22 July 2017 в 15:19

Поскольку вы используете синтаксис PCRE (Perl Compatible Regular Expressions), а sed не понимает этого, он использует Basic Regular Expressions (BRE) по умолчанию. Он не знает ни \s, ни \d. Вы также избегаете всевозможных вещей, которые не должны быть экранированы (ни \=, ни \> ничего полезного не делают], не избегая тем, что нужно экранировать (+ просто означает символ + в BRE, вам нужно \+ для «одного или нескольких».

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

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

Или, используя расширенные регулярные выражения: [ ! d2] sed -E 's/"\s*width="[0-9]+">//g' file

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

17
ответ дан 18 July 2018 в 09:55

Поскольку вы используете синтаксис PCRE (Perl Compatible Regular Expressions), а sed не понимает этого, он использует Basic Regular Expressions (BRE) по умолчанию. Он не знает ни \s, ни \d. Вы также избегаете всевозможных вещей, которые не должны быть экранированы (ни \=, ни \> ничего полезного не делают], не избегая тем, что нужно экранировать (+ просто означает символ + в BRE, вам нужно \+ для «одного или нескольких».

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

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

Или, используя расширенные регулярные выражения: [ ! d2] sed -E 's/"\s*width="[0-9]+">//g' file

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

17
ответ дан 24 July 2018 в 19:28

Вот мое решение 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
ответ дан 22 May 2018 в 20:20
  • 1
    Хорошая идея. Но -P в этом случае не требуется, и вместо .*\.gif я использовал бы [^\"]*. Это будет менее конкретным. – RoVo 21 July 2017 в 15:54
  • 2
    Да, отредактирован ... Я тестировал что-то, что не сработало;) – Ravexina 21 July 2017 в 15:55
  • 3
    Лучшим подходом, использующим grep, будет grep -oP '.*(?=" width="\d+">)' file, так как i) не предполагает наличие какой-либо строки (например, «веб-сайт» в вашем примере), не упомянутой OP, и ii) использует ту же основную идею, что и OP, поэтому мы можем быть уверены, что он будет соответствовать их данным. – terdon♦ 21 July 2017 в 16:00
  • 4
    @terdon Я добавлю сейчас в будущее решение;) спасибо. – Ravexina 21 July 2017 в 16:01
  • 5
    Существуют сотни рабочих решений с grep и sed. Я люблю это. – RoVo 21 July 2017 в 16:02

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

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

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

1
ответ дан 22 May 2018 в 20:20

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

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

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

Вот как это выглядит с вашей конкретной командой:

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

Если вы используете одинарные кавычки вокруг поиска и замены, вам не нужно избегать символов ", которые появляются в нем, или отслеживать использование оболочки для Perl для текста с двойным кавычком. Это упростит запись и чтение. (Это не относится к 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

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

Вместо sed -i используйте perl -pi -e. Выполнение операций поиска и замены по нескольким файлам Вместо из sed -i.bak, используйте perl -pi.bak -e. (Вы можете использовать любой суффикс, это не должно быть .bak.)
0
ответ дан 22 May 2018 в 20:20

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

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

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

Вот как это выглядит с вашей конкретной командой:

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

Если вы используете одинарные кавычки вокруг поиска и замены, вам не нужно избегать символов ", которые появляются в нем, или отслеживать использование оболочки для Perl для текста с двойным кавычком. Это упростит запись и чтение. (Это не относится к 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

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

Вместо sed -i используйте perl -pi -e. Выполнение операций поиска и замены по нескольким файлам Вместо из sed -i.bak, используйте perl -pi.bak -e. (Вы можете использовать любой суффикс, это не должно быть .bak.)
0
ответ дан 18 July 2018 в 09:55

Вот мое решение 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
ответ дан 18 July 2018 в 09:55

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

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

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

1
ответ дан 18 July 2018 в 09:55

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

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

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

Вот как это выглядит с вашей конкретной командой:

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

Если вы используете одинарные кавычки вокруг поиска и замены, вам не нужно избегать символов ", которые появляются в нем, или отслеживать использование оболочки для Perl для текста с двойным кавычком. Это упростит запись и чтение. (Это не относится к 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

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

Вместо sed -i используйте perl -pi -e. Выполнение операций поиска и замены по нескольким файлам Вместо из sed -i.bak, используйте perl -pi.bak -e. (Вы можете использовать любой суффикс, это не должно быть .bak.)
0
ответ дан 24 July 2018 в 19:28

Вот мое решение 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
ответ дан 24 July 2018 в 19:28
  • 1
    Хорошая идея. Но -P в этом случае не требуется, и вместо .*\.gif я использовал бы [^\"]*. Это будет менее конкретным. – RoVo 21 July 2017 в 15:54
  • 2
    Да, отредактирован ... Я тестировал что-то, что не сработало;) – Ravexina 21 July 2017 в 15:55
  • 3
    Лучшим подходом, использующим grep, будет grep -oP '.*(?=" width="\d+">)' file, так как i) не предполагает наличия какой-либо строки (например, «веб-сайт» в вашем примере), не упомянутой OP, и ii) использует ту же основную идею, что и OP, поэтому мы можем быть уверены, что он будет соответствовать их данным. – terdon♦ 21 July 2017 в 16:00
  • 4
    @terdon Я добавлю сейчас в будущее решение;) спасибо. – Ravexina 21 July 2017 в 16:01
  • 5
    Существуют сотни рабочих решений с grep и sed. Я люблю это. – RoVo 21 July 2017 в 16:02

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

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

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

1
ответ дан 24 July 2018 в 19:28

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

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