sed: Ignore os espaços em branco iniciais ao substituir globalmente

sed: Ignore os espaços em branco iniciais ao substituir globalmente

Estou tentando escrever um comando sed para substituir espaços excessivos em um arquivo. Cada palavra deve ter apenas um espaço entre as palavras, mas os espaços iniciais e tabulações devem ser deixados em paz. Então o arquivo:

     This is     an indented      paragraph. The   indentation   should not be changed.
This is the     second   line  of the    paragraph. 

Se tornará:

     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

Eu tentei variações de

/^[ \t]*/!s/[ \t]+/ /g

Qualquer idéia seria apreciada.

Responder1

$ sed 's/\>[[:blank:]]\{1,\}/ /g' file
     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

A expressão que usei corresponde a um ou vários [[:blank:]](espaços ou tabulações)depois de uma palavrae os substitui por um único espaço. Corresponde \>ao limite de largura zero entre um caractere de palavra e um caractere que não é de palavra.

Isso foi testado com o nativo do OpenBSD sed, mas acho que deveria funcionar com o GNU sedtambém. GNU sedtambém usa \bpara combinar limites de palavras.

Você também pode usar sed -Epara encurtar isso para

sed -E 's/\>[[:blank:]]+/ /g' file

Novamente, se \>não funcionar para você com GNU sed, use \b.


Observe que, embora o texto acima classifique seu texto de exemplo da maneira correta, isso nãobastantetrabalho para remover espaços após a pontuação, como após a primeira frase em

     This is     an indented      paragraph.        The   indentation   should not be changed.
This is the     second   line  of the    paragraph.

Para isso, uma variante um pouco mais complicada resolveria o problema:

$ sed -E 's/([^[:blank:]])[[:blank:]]+/\1 /g' file
     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

Isso substitui qualquer caractere que não esteja em branco seguido por um ou mais caracteres em branco pelo caractere que não esteja em branco e um único espaço.

Ou, usando o padrão sed(e uma otimização muito pequena, pois só fará a substituição se houverdois ou maisespaços/tabulações após o não-espaço/tabulação),

$ sed 's/\([^[:blank:]]\)[[:blank:]]\{2,\}/\1 /g' file
     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

Responder2

POSIXamente:

sed 's/\([^[:space:]]\)[[:space:]]\{1,\}/\1 /g; s/[[:space:]]*$//'

Que substitui qualquer sequência de um ou mais caracteres de espaço em branco após um não-espaço em branco, por esse não-espaço em branco e um único caractere SPC, e remove os caracteres de espaço em branco à direita, o que cobriria linhas em branco e linhas com espaço em branco à direita (incluindo os CRs encontrados em o final das linhas provenientes de arquivos de texto da Microsoft).

informação relacionada