Se você qualificar palavra para significar qualquer sequência de 1 ou mais caracteres não em branco , a resposta é definitivamente sim, e também é muito simples. Isto porque [[:blank:]]*
e [^[:blank:]]*
são complementos boolean e - fornecidos todos os caracteres em uma seqüência estão completos - [[:blank:]]*
U [^[:blank:]]*
pode descrever qualquer seqüência possível, da mesma maneira .*
faz.
Se um caractere incompleto ou uma sequência de bytes inválida existir em uma sequência, não será possível descrevê-la com êxito da cabeça para a cauda - como às vezes pode ocorrer ao interpretar uma sequência na codificação incorreta. Para garantir um caractere completo por byte em qualquer sequência, o código de idioma C pode ser forçado como:
LC_ALL=C sed ...
... o que evitaria quaisquer problemas que descrevessem a corda da cabeça à cauda com um padrão abrangente, como .*
ou([ ]*[^ ]*)*
Um padrão totalmente complementar pode repetir quantas vezes for necessário, da esquerda para a direita, o comprimento de qualquer string para aterrissar na última ocorrência possível, sem nenhuma interrupção no padrão. Definitivamente, essa é uma linguagem comum.
BRE:
sed 's/\(\([^[:blank:]]*\)[[:blank:]]*\)*/\2/'
ANTES:
sed -E 's/(([^[:blank:]]*)[[:blank:]]*)*/\2/'
Ambas as versões ainda imprimirão linhas em branco, e isso ocorre porque a *
estrela Kleene corresponde a zero ou mais ocorrências de um padrão. Primeiro, corresponde a zero ou mais caracteres em branco, zero ou mais caracteres em branco e, em seguida, zero ou mais ocorrências das correspondências agrupadas até corresponder à sequência na íntegra.
Tendo correspondido tudo isso, a mágica acontece na substituição - as referências retornadas por grupos \1
e \2
são as últimas ocorrências de cada uma. Portanto, quando a substituição é feita, toda a cadeia é substituída apenas pela última ocorrência em uma linha de zero ou mais caracteres não em branco - ou do subgrupo \2
.
É claro que isso funciona para qualquer sequência possível - mesmo uma vazia - o que significa que os dois formulários imprimirão caracteres de nova linha para linhas que contêm apenas caracteres em branco ou nenhum. Para lidar com isso, há algumas coisas que você pode fazer, mas primeiro vamos facilitar a digitação da classe de personagem:
b='[:blank:]'
Agora, para imprimir apenas se uma linha contiver um ou mais caracteres que não estão em branco, você pode:
BRE:
sed -n "s/\(\([^$b]*\)[$b]*\)*/\2/;/./p"
ANTES:
sed -En "/[^$b]/s/(([^$b]*)[$b]*)*/\2/p"
- Caso BRE - a substituição é sempre realizada e apenas os espaços do padrão com pelo menos um caractere restante são impressos.
- Caso ERE - a substituição só é tentada em um espaço padrão contendo pelo menos um caracter não em branco.
Qualquer um dos formulários funcionará com qualquer um dos métodos - desde que a sintaxe esteja correta.
O -n
comutador desativa a impressão automática do espaço do padrão e o p
sinalizador para os comandos s///
ubstitution ou /
address /
imprime seus resultados somente se for bem-sucedido.
Essa mesma lógica pode ser aplicada para obter qualquer {num}
ocorrência, como:
BRE:
sed -n "s/\([$b]*\([^$b]\{1,\}\)\)\{num\}.*/\2/p"
ANTES:
sed -En "s/([$b]*([^$b]+)){num}.*/\2/p"
... em que os num
dois regexps podem ser substituídos por um número para imprimir apenas a {num}
ocorrência especificada de uma sequência de caracteres que não estão em branco. Uma forma ligeiramente diferente é usada aqui para garantir que a contagem não seja inclinada para o espaço inicial em uma sequência.
Observe que o -E
switch ERE para sed
é suportado nas versões BSD e GNU, embora ainda não seja a sintaxe padrão do POSIX.
sed
?