use sed para substituir nbsp, 160, Hex 00a0, Octal 240, espaço sem quebra

8

Estou tendo alguns problemas com os arquivos de configuração que contêm os caracteres de espaço ininterrupto.

Como devo especificar esse caractere com sed para que eu possa substituí-lo por um espaço.

sed -n 's/ / /g'

exemplos dos erros

serviço chamado restart
Parando com o nome: [OK]
Começando com o nome: 
Erro na configuração nomeada:
named.localhost: 2: tipo RR desconhecido 'SOA'
named.localhost: 8: tipo desconhecido de RR '@'
named.localhost: 9: tipo desconhecido de RR '127.0.0.1'
named.localhost: 10: tipo desconhecido de RR ':: 1'
.....

Eu tentei incluir uma linha do arquivo incorreto original neste post. Não parece estar funcionando. O download do Pastebin é a única ferramenta que mantém todo o binário original. http://pastebin.com/ZqT1EWbS . Você deve copiar e colar a linha original e fazê-la funcionar em seu terminal.

nelaaro
fonte
você pode pesquisar no manual do sed e procurar hexadecimal que verá que pode especificar caracteres em hexadecimal, por exemplo, o espaço sem quebra \ xA0 Você também pode especificar em decimal. \ d160 mas você sabe que, ao procurar hexadecimal no manual, estaria falando sobre a especificação de caracteres em hexadecimal. Há um pequeno punhado de menções de casas decimais, portanto não é difícil procurar casas decimais no manual. Eu tenho um manual para o GNU 4.2.1 do Sed. Possui cerca de \ d e \ x especificando hex.
barlop
@barlop você pode colar um link para a documentação que demonstra o uso hexadecimal e decimal do sed.
Nelaaro 12/12
o meu é do gnuwin32 sed vem com um pdf. Existe um manual on-line aqui gnu.org/software/sed/manual/sed.html do edit..find..hex, você encontra o mesmo conteúdo (embora eu veja em um lugar, um cabeçalho como "alguns scripts de amostra" no meu pdf, vs "exemplos" nesse, diferem um pouco), mas a maior parte do resto é a mesma palavra por palavra, eu poderia editar ... encontrar frases em uma e encontrar o mesmo conteúdo na outra e os mesmos títulos significativos menores também. então os detalhes são os mesmos. Parece ser provavelmente quase idêntico ao que tenho.
barlop

Respostas:

17

A resposta a esta pergunta depende de qual dos caracteres espaciais que você está encontrando.

Abaixo estão exemplos de como substituir cada um dos caracteres de espaço sem quebra mencionados no título das perguntas e, adicionalmente, a versão UTF-8 ( C2 A0) que o OP está realmente perguntando de acordo com a saída do pastebin.

Todos os exemplos são usados printfpara gerar a saída, pois é mais portátil que echo. Os caracteres de espaço são substituídos por X's para tornar a saída mais clara.

Exemplos

html

printf '&#nbsp;\n' | sed 's/ /X/g'
printf ' \n'  | sed 's/&160;/X/g'
printf ' \n'  | sed 's/&[aA]0;/X/g'

octal 240 = decimal 160 = hex A0

printf '\xA0\n' | sed 's/\xA0/X/g'

Ou com tr:

printf '\xA0\n' | tr '\240' 'X'

U + 00A0

printf '\x00\xA0\n' | sed 's/\x00\xA0/X/g'

UTF-8

printf '\xC2\xA0\n' | sed 's/\xC2\xA0/X/g'

Resultado

A saída em todos os casos acima é:

X

Responda

Agora, para sua pergunta, você tem dados parecidos com este:

printf '@       IN SOA  @ rname.invalid. (' | od -x

Saída:

0000000 c240 c2a0 c2a0 c2a0 c2a0 c2a0 20a0 4e49
0000020 5320 414f a0c2 4020 7220 616e 656d 692e
0000040 766e 6c61 6469 202e 0a28
0000052

Para substituir os C2 A0s por espaço comum, use o seguinte:

printf '@       IN SOA  @ rname.invalid. (' | sed 's/\xC2\xA0/ /g' | od -x

Saída:

0000000 2040 2020 2020 2020 4e49 5320 414f 2020
0000020 2040 6e72 6d61 2e65 6e69 6176 696c 2e64
0000040 2820 000a
0000044
Thor
fonte
o que o -n faz? talvez eu tenha feito algo errado, mas sem -n funciona. com -n fico sem saída eo arquivo permanece o mesmo
barlop
@ Barlop: faz com que o sed não imprima o espaço do padrão e não deveria estar lá. Corrigido, obrigado.
Thor
Se alguém quiser fazer o sed de maneira destrutiva e não construtiva (para pegar emprestada uma frase que eu acho que é da programação), você pode fazer C: \> sed -i "s / \ xA0 / / g" a.txt É provavelmente melhor faça-o construtivamente como você tem. Mas essa é uma linha que não mostra nada na tela, mas faz alguma coisa (mencionei isso porque mencionamos suprimir a saída). sed -it grava o resultado em a.txt ou funciona em a.txt, para que a saída desejada esteja lá e nenhuma saída na tela.
barlop
2
Eu provavelmente adicionaria à resposta do @ barlop para sugerir, assumindo que eles desejam salvar as alterações no arquivo. sed -i.orig 's/\xa0/ /g'Dessa forma, ele não atualiza o arquivo original, mas salva o original como originalname.txt.orig(ou qualquer extensão especificada, como .bak)
nerdwaller
11
O espaço sem interrupção Unicode é U + 00A0, codificado como C2 A0 em UTF-8. Se o seu arquivo estiver codificado em UTF-8, sed 's/\xa0/ /g'você removerá apenas o caractere A0 e deixará o C2. Ou seja, pelo menos o comportamento que estou vendo, mesmo com um código de idioma UTF-8 em uso.
Seppo Enarvi
2

Obrigado por todos aqueles que me ajudam a chegar a uma solução funcional.

Eu tentei incluir uma linha do arquivo incorreto original neste post. Não parece estar funcionando. O download do Pastebin é a única ferramenta que mantém todo o binário original. http://pastebin.com/ZqT1EWbS . Você deve copiar e colar a linha original e fazê-la funcionar em seu terminal.

Então, aqui está o que acontece se eu remover o octal \0240ou o hex \xA0. Ele adiciona alguns outros personagens descolados.

$ echo "@ IN SOA @ rname.invalid. (" | sed -e "s / \ xA0 // g"
@        EM SOA  @ rname.invalid. (

Existem alguns dados extras não impressos nos arquivos reais. Eu achei a ferramenta od (octal dump) bastante útil para me mostrar quais são os valores reais de hex / oct / binário para toda a linha.

$ echo "@ IN SOA @ rname.invalid. (" | od -x
0000000 c240 c2a0 c2a0 c2a0 c2a0 c2a0 20a0 4e49
0000020 5320 414f a0c2 4020 7220 616e 656d 692e
0000040 766e 6c61 6469 202e 0a28
0000052

O outro caractere que continuava aparecendo era \xC2Ele não é impresso quando o espaço \xA0não está presente, mas aparece se o nbsp for removido. Então eu tive que modificar a linha sed na resposta @Thor para removê-la também.

Isto é o que funcionou para mim.

$ echo "@ IN SOA @ rname.invalid. (" | sed -e "s / \ xC2 \ xA0 / / g"
@ SOA @ rname.invalid. (
nelaaro
fonte
parece que os caracteres são quebrados ao colocá-lo em pastebin também. Aqui está a saída que recebo dessa linha de eco pastebin.com/raw.php?i=KfWPSXWN observe que o hex é diferente do seu hex. Você pode enviar o arquivo para ge.tt ? (Eu sei que você resolveu ainda vale a pena).
barlop
@barlop ge.tt/72UA2QT/v/0
nelaaro
pastebin.com/raw.php?i=ZqT1EWbS não funciona. Acesse o link diretamente pastebin.com/ZqT1EWbS . e use a seção bruta na parte inferior. Eu testei e funcionou como eu esperava. Eu acho que provavelmente tem algo a ver com o navegador / servidor / php fazendo a conversão / filtragem de caracteres.
Nelaaro 12/12
Eu acho que espaços sem quebra podem sair engraçados quando você os coloca em alguns comandos, incluindo od. então, para mim, faça eco a <espaços não brekaing> | od -tx1 imprime 61 ff ff ff ff ff ff ff ff ff ff 0d 0a. Então, para remover meus espaços não quebráveis, eu tenho que fazer eco ab | sed "s / \ xff / we / g" Seus espaços ininterruptos ficam engraçados, mas um código engraçado diferente do meu código engraçado. (Eu posso copiar / colar espaços sem interrupção que ecoam as saídas, para que o eco não estrague tudo, mas eles ficam bagunçados quando canalizados). Então, o que nós somos capazes de fazer, é o uso sed mas nos códigos desarrumada, e nós vê-los com od ..
barlop
e, a propósito, sugiro od -tx1 ou -td1 para decimal. pois acho que fica mais claro assim e você também pode. Estranhamente, as coisas podem sair de trás para frente. Tente eco abc | od -x. Então tente com | od -tx1 Não sei por que, quando você fez od -x, não saiu para trás ou talvez não tenha certeza. Não posso testar porque meu código codificado era ff. Mas compare -tx1 com -x e veja o que você pensa.
barlop