Com o padrão sed, você nunca verá uma nova linha no texto lido de um arquivo. Isso ocorre porque sedlê linha por linha e, portanto, não há nova linha no final do texto da linha atual no sedespaço do padrão. Em outras palavras, sedlê dados delimitados por nova linha e os delimitadores não fazem parte do que um sedscript vê.
Expressões regulares podem ser ancoradas no final da linha usando $(ou no início, usando ^). A ancoragem de uma expressão no início / fim de uma linha obriga a corresponder exatamente lá, e não apenas em qualquer lugar na linha.
Se você deseja substituir algo que corresponda ao padrão [A-Za-z]*no final da linha por algo, ancore o padrão da seguinte maneira:
[A-Za-z]*$
... forçará a correspondência no final da linha e em nenhum outro lugar.
No entanto, como [A-Za-z]*$também não corresponde a nada (por exemplo, a cadeia vazia presente no final de cada linha), você precisa forçar a correspondência de algo , por exemplo, especificando
[A-Za-z][A-Za-z]*$
Portanto, sua linha de comando sed será assim
$ sed 's/[A-Za-z][A-Za-z]*$/replace/' file.txt
Eu não usei o -Eswitch aqui porque não é necessário. Com isso, você poderia ter escrito
Embora eu saiba como fazer isso, você receberá um +1 apenas pelo uso do termo técnico. :) Então isso é chamado de ancoragem - é bom saber. Por enquanto, eu sempre tive que parafrasear ... Outra observação sobre+ : você pode usá-lo mesmo sem usar o regex extendido, lembre-se de escrevê-lo como \+. Então sed -e 's/[A-Za-z]\+$/replace/' file.txt, funcionará perfeitamente mesmo sem o GNU sedinstalado. E não se esqueça: Não use -E, pois o GNU sednão suporta .
SyntaxError
1
@ syntaxerror - Eu acho que você pode remover a última frase ou, pelo menos, desdobrar, como gnu seddefinitivamente suporta-E .
don_crissti
@don_crissti Bem, eu pensei que você estivesse nesta rede há tempo suficiente para saber que não há como desdobrar partes de um comentário (a menos que você o reescreva inteiramente). Então, deixe-me corrigir: O GNU sedpode suportar "silenciosamente" -E, mas não está documentado na página de manual (nem no manual do Texinfo (verifique os dois)). Por isso, presumi que não era suportado (o que era uma suposição errada, afinal). De qualquer forma, você está certo, porque pelo menos o GNU sednão vai reclamar se você usar esta opção.
Syntaxerror #
@don_crissti Fico feliz que você fez! Portanto, pelo menos foi confirmado que sedserá necessária uma opção específica que ainda não foi devidamente documentada. Isso sempre é útil; se ninguém estiver ciente da falta de documentação, ninguém nunca a corrigirá.
Syntaxerror 15/11/2015
@syntaxerror, consulte unix.stackexchange.com/a/310454/135943 . Obviamente, se você precisar trabalhar com sistemas antigos como o RHEL 5, estará usando uma versão GNU sed que não suporta -E.
Wildcard
3
sed "s/[a-zA-Z]*$/replace/" input.txt > result.txt
Ou, a maneira desnecessária e complexa:
Eu descobri, isso pode ser feito, ainda usando sed, com a ajuda de tr. Você pode atribuir outro caractere para representar o final da linha. Outro caractere temporário deve ser usado, neste caso "" ". Vamos usar "~" para representar o final da linha:
Não tenho certeza de que entendi ... Por que você não se ancora no final da linha $? por exemplos/[a-zA-Z]*$/replace/
don_crissti 01/06/2015
1
2 pontos: 1) É melhor usar ao \+invés de, *pois o último permite zero letras no final da string; 2) Você pode usar uma classe de personagem [[:alpha:]]. Então:sed 's/[[:alpha:]]\+$/replace/' file
glenn jackman
@glennjackman Para que serve a barra invertida antes do sinal de mais? Isso não corresponderia ao caractere de adição?
No snippet de código (quebrado) que você postou, parece que você deseja substituir a nova linha também. Nesse caso, a ancoragem regex por si só não pode ajudá-lo. A seguir está uma solução:
sed '/[[:alpha:]]\+$/{N;s/[[:alpha:]]\+\n/replace/}' your_file
Quebrado:
/[a-zA-Z]\+$/{} significa aplicar o que estiver dentro dos curlies às linhas que correspondem ao regex.
Dentro das curvas, Nsignifica "anexar a próxima linha ao buffer ativo" (o que sedchama de 'espaço padrão')
Finalmente, a s///declaração é a sua substituição necessária. Agora funciona porque o espaço do padrão contém duas linhas sucessivas e, portanto, a nova linha faz parte dele.
+
: você pode usá-lo mesmo sem usar o regex extendido, lembre-se de escrevê-lo como\+
. Entãosed -e 's/[A-Za-z]\+$/replace/' file.txt
, funcionará perfeitamente mesmo sem o GNUsed
instalado. E não se esqueça: Não use-E
, pois o GNUsed
não suporta .gnu sed
definitivamente suporta-E
.sed
pode suportar "silenciosamente"-E
, mas não está documentado na página de manual (nem no manual do Texinfo (verifique os dois)). Por isso, presumi que não era suportado (o que era uma suposição errada, afinal). De qualquer forma, você está certo, porque pelo menos o GNUsed
não vai reclamar se você usar esta opção.sed
será necessária uma opção específica que ainda não foi devidamente documentada. Isso sempre é útil; se ninguém estiver ciente da falta de documentação, ninguém nunca a corrigirá.-E
.Ou, a maneira desnecessária e complexa:
fonte
$
? por exemplos/[a-zA-Z]*$/replace/
\+
invés de,*
pois o último permite zero letras no final da string; 2) Você pode usar uma classe de personagem[[:alpha:]]
. Então:sed 's/[[:alpha:]]\+$/replace/' file
-r
opção usa esta sintaxe de expressão regular .No snippet de código (quebrado) que você postou, parece que você deseja substituir a nova linha também. Nesse caso, a ancoragem regex por si só não pode ajudá-lo. A seguir está uma solução:
Quebrado:
/[a-zA-Z]\+$/{}
significa aplicar o que estiver dentro dos curlies às linhas que correspondem ao regex.N
significa "anexar a próxima linha ao buffer ativo" (o quesed
chama de 'espaço padrão')s///
declaração é a sua substituição necessária. Agora funciona porque o espaço do padrão contém duas linhas sucessivas e, portanto, a nova linha faz parte dele.fonte
Para encontrar o final da linha, basta usar o $ -sign :
Sem âncora no final da linha:
Sem âncora no final da linha:
fonte