У меня есть файл с несколькими строками, которые берутся из текста в формате HTML, поэтому в них есть некоторые последовательности HTML, которые не очень хорошо выглядят в интерфейсе консоли. Вот пример:
Text1™
[Text®2]
Text:3
Я пытаюсь удалить все между & и ;, чтобы текст снова стал читаемым, как показано ниже:
Text1
Text2
Text3
На самом деле я пытаюсь использовать sed, чтобы удалить лишние символы:
sed 's#&*;##g' <file>
Проблема в том, что он удаляет только ; из текстовых строк.
Тогда возникает вопрос, как следует закодировать выражение регулярного выражения, чтобы удалить лишнюю цепочку:&#[1-9]+;
решение1
Ваше регулярное выражение
sed 's#&*;##g' <file>
не делает то, что вы думаете. Символ *
является множителем, который говорит, что предыдущий символ повторяется 0 или более раз. Предыдущий символ — &
, поэтому это будет соответствовать, например, &&&;
и ;
( &
записано 0 раз до ;
! Это то, что соответствует в ваших тестовых случаях), но не то, что вы хотите в этом случае.
Вам необходимо указать "любойсимвол» перед множителем, который представлен одной точкой, .
.
$ echo 'Text:3' | sed 's#&.*;##g'
Text3
Это была первая проблема. Вторая — это концепция так называемого «жадного» сопоставления: sed
увидит первую &
и попытается сопоставить самую большую строку, какую только сможет. Если у вас несколько HTML-сущностей на одной строке, это будет проблемой, поскольку:
$ echo 'Text:3 and some more text å and end' | sed 's#&.*;##g'
Text and end
Если вы хотите увидеть исправление в sed
контексте, вы можете поискать конечный символ сущности, сопоставив любое количество "нет ;
" перед закрытием, ;
выполнив:
$ echo 'Text:3 and some more text å and end' | sed 's#&[^;]*;##g'
Text3 and some more text and end
У вас по-прежнему будут проблемы с допустимым использованием знака амперсанда ( &
) в тексте (ну, &
это действительно «допустимое» использование, но реальный мир не всегда так же поддается анализу, как идеальный) и слишком большим количеством соответствий, но это объясняет, почему sed
он ведет себя именно так.
решение2
Не лучше ли заменить коды реальными символами?
echo 'Text1™
[Text®2]
Text:3' | perl -C -pe 's/&#([^;]*)/chr$1/eg'
Выход:
Text1™;
[;Text®;2];
Text:;3