Как удалить » `сохранить этот текст» ` с помощью sed или perl?

#regex #bash #macos #sed #grep

Вопрос:

Как я могу удалить весь <a href="file://???"> этот текст </a> , но не другой <a></a> , или </a> использовать sed или perl?
Является:

     <p><a class="a" href="file://any" id="b">keep this text</a>, <a href="http://example.com/abc">example.com/abc</a>, more text</p>
 

Должно быть:

     <p>keep this text, <a href="http://example.com/abc">example.com/abc</a>, more text</p>
 

У меня есть такое регулярное выражение, но оно слишком жадное и удаляет все </a>

 gsed -E -i 's/<a*href="file:[^>]*>(. ?)</a>/1>/g' file.xhtml
 

Комментарии:

1.рассмотрите возможность обновления вопроса более репрезентативным набором данных, в частности … вы упомянули remove all , что подразумевает, что вы, возможно, захотите удалить несколько записей, поэтому пример, показывающий несколько записей, был бы полезен; кроме того, вы хотите удалить все file: записи или только определенные?

Ответ №1:

Допущения:

  • OP не имеет доступа к инструменту, ориентированному на HTML
  • удалите <a href="file:..."> …some_text… </a> обертки, оставив только ...some_text...
  • применяется только к file: записям
  • входные данные не имеют разрыва строки/подачи в середине file: записи

Примеры данных, показывающие несколько file: записей, чередующихся с некоторыми другими (бессмысленными) записями:

 $ cat sample.html
<p><a href="https:/google.com">some text</a><a href="file://any" >keep this text</a>, <a href="http://example.com/abc">example.com/abc</a>, more text</p><a href="file://anyother" >keep this text,too</a>, last test</p>
 

Одна sed идея-удалить обертки для всех file: записей:

 sed -E 's|<a[^<>] file:[^>] >([^<] )</a>|1|g' "${infile}"
 

ПРИМЕЧАНИЕ: возможно, немного перебор с некоторыми [^..] записями, но ключевая цель состоит в том, чтобы замкнуть sed's жадное соответствие по умолчанию …

Это оставляет:

 <p><a href="https:/google.com">some text</a>keep this text, <a href="http://example.com/abc">example.com/abc</a>, more text</p>keep this text,too, last test</p>
 

Комментарии:

1. твой код работает на меня. Спасибо! Он работает с macOS sed и GNU sed, и на данный момент он самый короткий.

Ответ №2:

В одну сторону:

 sed -E 's,<a[^>]*?href="file://[^>]*>([^<]*)</a>,1,g'
 
  • <a[^>]*?href="file://[^>]*> совпадение <a любое количество не- > (не-жадных), за которыми следует href="file:// любое количество не — > символов, за которыми следует >
  • ([^<]*) сопоставьте и захватите любое количество несимвольных < символов
  • матч на </a>

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

Примеры:

 $ cat data
<p><a class="a" href="file://any" id="b">keep this text</a>, <a id="file:ex" href="http://example.com/abc">example.com/abc</a>, more text</p>
<p><a href="file://any" class="f">keep this text</a>, <a href="http://example.com/abc">example.com/abc</a>, more text</p>
 
 $ sed -E 's,<a[^>]*?href="file://[^>]*>([^<]*)</a>,1,g' < data
<p>keep this text, <a id="file:ex" href="http://example.com/abc">example.com/abc</a>, more text</p>
<p>keep this text, <a href="http://example.com/abc">example.com/abc</a>, more text</p>
 

Комментарии:

1. Спасибо, этот тоже работает, однако он работает только с GNU sed, но он выполняет свою работу.

2. @user3464412 Пожалуйста, но это должно работать с любым Posix sed , если я не ошибаюсь. Я попробовал sed -E --posix , и это дает тот же результат.

Ответ №3:

Учитывая тот случай <a> , когда тег состоит из содержимого в нескольких строках, как насчет perl решения:

 perl -0777 -i -pe 's#<a. ?href="?file. ?>(. ?)</a>#$1#gs' file.xhtml
 
  • -0777 Опция указывает perl проглотить весь файл целиком.
  • Эта -i опция позволяет редактировать на месте.
  • s Переключатель в конце s оператора заставляет точку совпадать с любыми символами, включая символ новой строки.
  • Регулярное выражение . ? -это не жадная версия . , позволяющая обеспечить кратчайшее совпадение.