sed se comporta de maneira diferente no FreeBSD e no Linux?

12

Eu uso Linux e FreeBSD (especificamente, eu uso Debian Linux e PC-BSD), e eu encontrei algo estranho sobre sed .

Freqüentemente preciso converter arquivos "valores separados por guias" em "valores separados por vírgulas". A maneira mais simples que conheço é usar sed , assim:

sed 's/\t/,/g' inputFile.txt > outputFile.csv

Isso funciona perfeitamente no Linux: Ele substitui todas as guias por vírgulas ... mas no FreeBSD, isso não substitui nada!

Estou faltando alguma coisa? Existe uma sintaxe com o FreeBSD sed que é diferente da do Linux?

    
por Barranka 13.11.2013 / 18:55

5 respostas

9

Talvez você deva usar a opção -E (ou -r conforme explicado no manual ) para manter a compatibilidade com o GNU Sed. No seu caso, você pode instalar o Gnu Sed se estiver acostumado (port gsed no FreeBSD), ou será necessário um longo esforço para portar scripts.

E lembre-se. Se algum comando no BSD não agir como a versão gnu desse utilitário, isso não significa que ele está quebrado;)

    
por 13.11.2013 / 19:39
6

Sim, existem várias diferenças, o comportamento de -i é o único que conheço o topo da minha cabeça.

Eu nunca usei o BSD, então não posso ajudar com os detalhes, mas uma solução alternativa é usar tr :

tr '\t' , < inputFile.txt > outputFile.csv

Um efeito colateral agradável é que tr deve ser significativamente mais rápido. Eu testei isso no meu Linux usando um arquivo de teste com 50000 linhas, cada uma com 2 abas:

$ time tr '\t' , < foo.txt > /dev/null 

real    0m0.004s
user    0m0.000s
sys     0m0.000s

$ time sed 's/\t/,/g' foo.txt > /dev/null 

real    0m0.039s
user    0m0.036s
sys     0m0.000s
    
por 13.11.2013 / 19:02
4

Sim, diferentemente do GNU sed FreeBSD sed não interpreta sequências de escape ANSI C como \t em expressões regulares.

Uma maneira de obter um denominador menos comum neste caso é usar printf .

tab="$(printf '\t')"
printf '\t\n' | sed 's/'"${tab}"'/,/g'
printf '\t\n' | sed 's/'"$(printf '\t')"'/,/g'

O comportamento de sed -i para edições de arquivos no local pode ser compatível se um switch ou opção seguir imediatamente a opção -i , e. g. sed -i -e 's/x/X/g' file funciona tanto para o GNU sed quanto para o FreeBSD sed .

As versões recentes do FreeBSD sed (FreeBSD 8.1 ou mais recente) possuem a opção -r para aumentar a compatibilidade com o GNU sed .

(Além disso, o uso de classes de caracteres POSIX em sed expressões regulares é uma boa maneira de garantir compatibilidade também).

Para uma alternativa, implementação sed em conformidade com POSIX, consulte: minised - uma implementação de SED menor, mais barata e mais rápida .

    
por 27.11.2013 / 14:49
3

Você deve usar um caractere literal TAB em vez de \t :

sed 's/    /,/g' inputFile.txt > outputFile.csv

Veja este comentário por Stephane em outra pergunta.

O artigo a seguir também pode interessar a você:

cito a parte relevante:

Regex Differences

Regular expression syntax differs subtly between the different versions of SED. Most of the differences involve special escape patterns used to match non-printing characters, such as the ASCI bell and form feeds.

    
por 13.11.2013 / 19:01
0

Após o login, vejo o próximo anúncio e salve-o. Espero que seja útil para outros também

Want to use sed(1) to edit a file in place? Well, to replace every 'e' with an 'o', in a file named 'foo', you can do:

sed -i.bak s/e/o/g foo

And you'll get a backup of the original in a file named 'foo.bak', but if you want no backup:

sed -i '' s/e/o/g foo
    
por 13.07.2017 / 15:35

Tags