Eu sei usar sed
com a [^xxxx]
sintaxe para excluir caracteres, mas como faço para excluir uma palavra? Por exemplo minha variável:
var="
Now is the time
for all good men
to come
to the aid
of the party"
Agora:
echo $var | sed ...
... e quero terminar com:
REPLACED time
for all good men
to come
REPLACED aid
REPLACED party
... isso deve ser simples, mas não consigo descobrir como fazê-lo.
echo $var | sed -r 's/^[^the]*the/REPLACED/'
... é quase parecido, mas t
h
e
são correspondidos como caracteres individuais, não como a palavra the
.
Se houver soluções em que eu possa substituir tudo até a primeira de várias ocorrências, ou mesmo até uma ocorrência específica, seria ainda melhor.
Você pode conseguir isso da seguinte maneira, supondo que haja no máximo uma instância de
the
na linha :Isso substituirá tudo até a última ocorrência (lembre-se, RegExes são gananciosos) pelo
the
seu texto de substituição.the
, entre caracteres que não são palavras (para evitar correspondências parciais de palavras, comotheoretical
), incluindo o caractere que não é palavra que termina comthe
, em um grupo de captura( ... )
.\1
porque é o primeiro grupo desse tipo no padrão de pesquisa). Esse método um tanto complicado é necessário para que o caractere que termina othe
também seja transferido para o texto de substituição.Se quiser substituir tudo até à primeira ocorrência, poderá ter de recorrer a
awk
:Isso verificará se a string
the
, cercada por caracteres que não são palavras, ocorre na linha e armazenará a posição em uma variáveli
.i
for diferente de zero, imprimirá o texto de substituição e a substring da linha de entrada atual começando após a ocorrência dethe
, mas, caso contrário, pulará a execução para a próxima linha.i
for zero, ele simplesmente imprime a linha atual como está.s/.*the/REPLACED/
substitui tudo até a ocorrência mais à direita dethe
porque.*
é ganancioso e deseja corresponder o máximo possível..*
é 0 ou mais (*
) caracteres (.
) o máximo possível e engolirá alegremente todas as ocorrências dethe
não incluir o último que precisa ser correspondido pelathe
parte seguinte do regexp.Quase 30 anos atrás,
perl
5 introduziu uma variante de*
:*?
, que também corresponde a 0 ou mais da coisa anterior, mas o mínimo possível :Poucos
sed
s adicionaram suporte para esses novosperl
operadores. Conheço apenas duas implementações (ssed
with-R
, e ast-open's with-E
/-A
/-X
/-P
). Em outrossed
s,?
corresponde a um literal?
ou com-E
/-r
,*?
é um erro ou é o mesmo que*
é entendido como o*
operador (0 ou mais) combinado com?
(0 ou 1).Com
sed
implementações que não suportam*?
, quando a coisa a substituir é um único caractere comox
, você costumas/[^x]*x/REPLACE/
dizer 0 ou mais (*
) caracteres diferentes dex
([^x]
), tantos quanto possível, e porque excluímosx
, que serão armazenados antes do primeirox
ocorrência.Você não pode usar isso para strings de mais de um caractere, pois não pode dizer 0 ou mais caracteres o máximo possível, desde que isso não inclua "the" . Então você precisa de uma abordagem diferente.
s/the/REPLACEMENT/
substitui a primeira ocorrência dethe
, portanto, a abordagem comum no padrãosed
para substituir tudo até a primeira ocorrência de uma sequência de caracteres é substituí-la por uma nova linha (esse caractere é garantido para não ocorrer no espaço do padrão caso contrário) e, em seguida, substitua tudo até essa nova linha:Caso você precise substituir tudo pelo primeiro,
the
você pode precisar de quantificadores não gananciosos, e eles não são reconhecidos nem pela Expressão Regular Básica nem pela Expressão Regular Estendida.Nesse caso, se
sed
não for obrigatório para você, você pode usarperl
:E se precisar substituir até
n
a ocorrência (substituan
pelo seu número de ocorrência):