sed se comporta diferente en FreeBSD y en Linux?

12

Utilizo Linux y FreeBSD (específicamente, utilizo Debian Linux y PC-BSD), y encontré algo extraño sed.

Con frecuencia necesito convertir archivos de "valores separados por tabulaciones" a "valores separados por comas". La forma más simple que conozco es usar sed, así:

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

Esto funciona perfectamente en Linux: reemplaza cada pestaña con una coma ... pero en FreeBSD, ¡no reemplaza nada!

¿Me estoy perdiendo de algo? ¿Existe una sintaxis con FreeBSD sedque sea diferente a la de Linux?

Barranka
fuente

Respuestas:

9

Tal vez debería usar la -Eopción (o -rcomo se explica en el manual ) para mantener la compatibilidad con GNU Sed. En su caso, podría instalar Gnu Sed si está acostumbrado (puerto gsed en FreeBSD), o se necesitará un gran esfuerzo para portar scripts.

Y recuerda. Si algún comando en BSD no actúa como la versión gnu de esa utilidad, no significa que esté roto;)


fuente
1
Gracias. La -Eopción hace el truco (tanto en FreeBSD como en Mac OS X).
Barranka
En mi FreeBSD 9, la opción -E no ayuda.
Ark-kun
6

Sí, hay varias diferencias, el comportamiento de-i ser el único que conozco fuera de mi cabeza.

Nunca he usado BSD, así que realmente no puedo ayudar con los detalles, pero podría ser una solución alternativa en su trlugar:

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

Un efecto secundario agradable es que trdebería ser significativamente más rápido. Probé eso en mi Linux usando un archivo de prueba con 50000 líneas, cada una de las cuales tenía 2 pestañas:

$ 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
terdon
fuente
tr '\t' ,Es más portátil que tr $'\t' ,. tr '[\t]' '[,]'incluso sería portátil para algunos viejos sistemas SysV.
Stéphane Chazelas
tab es el delimitador predeterminado para cut. La especificación POSIX para trestá ahí . Me equivoqué sobre lo [necesario para el viejo SysV. Como señala la especificación POSIX, [solo es necesario para los rangos allí.
Stéphane Chazelas
@StephaneChazelas así es, lo siento, no estoy seguro de con qué lo estoy confundiendo entonces. Gracias por la aclaración en cualquier caso.
terdon
4

Sí, a diferencia de GNU sedFreeBSD sedno interpreta las secuencias de escape ANSI C como \ten las expresiones regulares.

Una forma de obtener un denominador menos común en este caso es usar printf.

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

El comportamiento de las sed -iediciones de archivos in situ puede hacerse compatible si un interruptor u opción sigue inmediatamente al -iinterruptor, por ejemplo, sed -i -e 's/x/X/g' filefunciona tanto para GNU sedcomo para FreeBSD sed.

Las versiones recientes de FreeBSD sed(FreeBSD 8.1 o más reciente) tienen el -rinterruptor para aumentar la compatibilidad con GNU sed.

(Además, el uso de clases de caracteres POSIX en sedexpresiones regulares también es una buena manera de garantizar la compatibilidad).

Para ver una sedimplementación alternativa conforme a POSIX, consulte: minised: una implementación SED más pequeña, más barata y más rápida .

kroy
fuente
3

Debe usar un TABcarácter literal en lugar de \t:

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

Vea este comentario de Stephane sobre otra pregunta.

El siguiente artículo también puede interesarle:

Cito la parte relevante:

Diferencias de

expresiones regulares La sintaxis de expresiones regulares difiere sutilmente entre las diferentes versiones de SED. La mayoría de las diferencias implican patrones de escape especiales que se utilizan para hacer coincidir los caracteres que no se imprimen, como la campana ASCI y los feeds de formularios.

Joseph R.
fuente
0

Después de iniciar sesión, veo el próximo anuncio y lo guardo. Espero que sea útil para otros también

¿Desea usar sed (1) para editar un archivo en su lugar? Bueno, para reemplazar cada 'e' con una 'o', en un archivo llamado 'foo', puede hacer:

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

Y obtendrá una copia de seguridad del original en un archivo llamado 'foo.bak', pero si no desea una copia de seguridad:

sed -i '' s/e/o/g foo
TradeNarK
fuente
sin embargo, la -iopción ya estaba cubierta
Jeff Schaller