no me dio la operación de sustitución correcta para newline con Mac-diferencias entre GNU sed y BSD/OSX sed
(2)
Esta pregunta ya tiene una respuesta aquí:
- Reemplazar la coma con nueva línea en sed 11 respuestas
Estoy usando esta referencia: sed help: haciendo coincidir y reemplazando un literal "/ n" (no la línea nueva)
y tengo un archivo "test1.txt" que contiene una cadena hola / ngoodbye
Uso este comando para buscar y reemplazar "/ n" con nuevos caracteres de línea reales:
sed -i '''' ''s///n//n/g'' test1.txt
pero el resultado es: hellongoodbye . simplemente reemplaza "/ n" con "n" y no una nueva línea real. Esto hace lo mismo con / t donde dejará una "t" y no una pestaña.
el '''' es para el error indefinido en MAC: http://mpdaugherty.wordpress.com/2010/05/27/difference-with-sed-in-place-editing-on-mac-os-x-vs-linux /
Actualización :
Probé los dos comandos que @ hek2mgl sugirió:
sed -i ''s///n//n/g'' test.txt
# Or:
sed -i'''' ''s///n//n/g'' test.txt
Si bien podrían funcionar con Linux, con MAC OS obtuve el siguiente error:
sed: 1: "test1.txt": undefined label ''est1.txt''
No estoy seguro de por qué no puedo hacer que esto funcione. Gracias por adelantado.
Esto puede parecer un poco extraño, pero prueba:
sed -i '''' ''s///n//
/g'' test1.txt
Es decir, use una nueva línea real en lugar de /n .
¡La explicación es que tienes un sed extraño! Para más detalles, consulte el manual mac sed: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/sed.1.html
En la descripción del comando s allí, dice:
A line can be split by substituting a newline character into it. To specify
a newline character in the replacement string, precede it with a backslash.
Además, en la descripción de la opción -i , dice que la extensión no es opcional, y que si no quiere una, debe especificar un argumento vacío. ¡Entonces todo tiene sentido al final!
Con BSD / macOS sed , para usar una nueva línea en la cadena de reemplazo de una llamada de función s , debe usar una nueva línea / -escaped actual - la secuencia de escape /n no es compatible allí (a diferencia de la parte de expresiones regulares de la llamada).
O bien : simplemente inserte una nueva línea real :
sed -i '''' ''s///n// /g'' test1.txtO bien : utilice una cadena ANSI C-entrecomillada (
$''...'') para empalmar en la línea nueva ($''/n''; funciona enbash,kshozsh):sed -i '''' ''s///n//'$''/n''''/g'' test1.txt
GNU sed , por el contrario, reconoce /n en cadenas de reemplazo; Siga leyendo para obtener una descripción general de las diferencias entre estas dos implementaciones.
Diferencias entre GNU sed (Linux) y BSD / macOS sed
macOS usa la versión de BSD de sed [1] , que difiere en muchos aspectos de la versión de GNU sed que viene con las distribuciones de Linux .
Su denominador común es la funcionalidad decretada por POSIX : ver la especificación POSIX sed .
El enfoque más portátil es usar solo las funciones de POSIX , que, sin embargo, limita la funcionalidad :
- En particular, POSIX especifica soporte sólo para expresiones regulares básicas , que tienen muchas limitaciones (por ejemplo, no admite nada para
|(alternancia), no admite directamente para+y?) Y diferentes requisitos de escape.- Advertencia: GNU
sed(sin-r), no admite/|,/+y/?, que NO es compatible con POSIX; use--posixpara deshabilitar (ver a continuación).
- Advertencia: GNU
- Para usar funciones POSIX solamente :
- (ambas versiones): use solo las opciones
-ny-e(especialmente, no use-Eo-rpara activar el soporte para expresiones regulares extendidas ) - GNU
sed: agregue la opción--posixpara garantizar la funcionalidad POSIX-only (no la necesita estrictamente, pero sin ella podría terminar inadvertidamente usando características que no sean POSIX sin darse cuenta; caveat :--posixsí mismo no es compatible con POSIX ) - El uso de características POSIX-only significa requisitos de formato más estrictos (renunciando a muchas comodidades disponibles en GNU
sed):- Las secuencias de caracteres de control tales como
/ny/tgeneralmente NO son compatibles. - Las etiquetas y los comandos de bifurcación (por ejemplo,
b) deben ir seguidos de una nueva línea o continuación real a través de una opción-eindependiente. - Ver abajo para más detalles.
- Las secuencias de caracteres de control tales como
- (ambas versiones): use solo las opciones
Sin embargo, ambas versiones implementan extensiones al estándar POSIX:
- qué extensiones implementan difiere (GNU
sedimplementa más). - incluso esas extensiones que ambos implementan difieren parcialmente en sintaxis .
Si necesita soportar AMBAS plataformas (discusión de diferencias):
- Características incompatibles :
- El uso de la opción
-isin un argumento (actualización in situ sin respaldo) es incompatible:- BSD
sed: DEBE usar-i '''' - GNU
sed: DEBE usar simplemente-i(equivalente:-i'''') - usar-i ''''NO funciona.
- BSD
-
-ienciende sensiblemente la numeración de líneas por archivo de entrada en GNUsedy versiones recientes de BSDsed(por ejemplo, en FreeBSD 10), pero NO en macOS a partir de 10.12 .
Tenga en cuenta que en ausencia de-itodas las líneas numéricas de las versiones se acumulan en todos los archivos de entrada. - Si la última línea de entrada no tiene una línea nueva final (y está impresa):
- BSD
sed: siempre agrega una nueva línea en la salida, incluso si la línea de entrada no termina en uno. - GNU
sed: conserva el estado de nueva línea final , es decir, agrega una línea nueva solo si la línea de entrada finaliza en uno.
- BSD
- El uso de la opción
- Características comunes :
- Si restringe sus scripts
seda lo que soporta BSDsed, generalmente funcionarán también en GNUsed, con la notable excepción de usar características de expresiones regulares extendidas específicas de la plataforma con-E. Obviamente, también renunciará a las extensiones que son específicas de la versión de GNU. Ver la siguiente sección.
- Si restringe sus scripts
Directrices para soporte multiplataforma (OS X / BSD, Linux), impulsado por los requisitos más estrictos de la versión BSD :
Tenga en cuenta que estoy usando los shorthands macOS y Linux para las versiones BSD y GNU de sed respectivamente, porque son las versiones en stock en cada plataforma. Sin embargo, es posible instalar GNU sed en macOS, por ejemplo, usando Homebrew con brew install gnu-sed .
Nota : Excepto cuando se usan los distintivos -r y -E (expresiones regulares extendidas ), las siguientes instrucciones equivalen a escribir scripts sed basados en POSIX .
- Para cumplir con POSIX, debe restringirse a POSIX BRE (expresiones regulares básicas ) , que, desafortunadamente, como su nombre lo indica, son bastante básicas.
Advertencia : no suponga que/|,/+y/?son compatibles: aunque GNUsedadmite (a menos que se use--posix), BSDsedno lo hace, estas funciones no son compatibles con POSIX.
Mientras/+y/?se puede emular en modo compatible con POSIX:
/{1,/}para/+,
/{0,1/}para/?,
/|(alternancia) no puede , desafortunadamente. Para expresiones regulares más potentes, use
-E(en lugar de-r) para admitir ERE (expresiones regulares extendidas ) (GNUsedno documenta-E, pero funciona allí como un alias de-r; versión más reciente de BSDsed, como en FreeBSD 10, ahora también es compatible con-r, pero la versión de macOS a partir de 10.10 no ).
Advertencia : aunque el uso de-r/-Esignifica que su comando, por definición, no es compatible con POSIX, debe restringirse a los ERE POSIX (expresiones regulares extendidas) . Lamentablemente, esto significa que no podrá usar varias construcciones útiles, en particular:- aserciones de límite de palabras, porque son específicas de la plataforma (por ejemplo,
/<en Linux,[[:<]]en OS X). - referencias hacia atrás dentro de expresiones regulares (en oposición a las "referencias retrospectivas" a las coincidencias de grupo de captura en la cadena de reemplazo de llamadas a función
s), porque BSDsedno las admite en expresiones regulares extendidas (pero, curiosamente, lo hace en los básicos , donde están ordenados por POSIX).
- aserciones de límite de palabras, porque son específicas de la plataforma (por ejemplo,
Secuencias de escape de caracteres de control como
/ny/t:- En las expresiones regulares (tanto en patrones para selección como en el primer argumento para la función
s), supongamos que solo/nse reconoce como una secuencia de escape (raramente utilizada, ya que el espacio de patrón suele ser una sola línea (sin terminación/n), pero no dentro de una clase de caracteres , por ejemplo,[^/n]no funciona; (si su entrada no contiene caracteres de control que no sean/t, puede emular[^/n]con[[:print:][:blank:]]; de lo contrario, empalme los caracteres de control. en como literales [2] ): generalmente, incluya los caracteres de control como literales , ya sea a través de cadenas entre comillas ANSI C (por ejemplo,$''/t'') en shells que lo soportan (bash,ksh,zsh), o mediante sustituciones de comandos usandoprintf(por ejemplo,"$(printf ''/t'')") .- Solo Linux
sed ''s//t/-/'' <<<$''a/tb'' # -> ''a-b'' - macOS y Linux:
sed ''s/''$''/t''''/-/'' <<<$''a/tb'' # ANSI C-quoted string
sed ''s/''"$(printf ''/t'')"''/-/'' <<<$''a/tb'' # command subst. with printf
- Solo Linux
En las cadenas de reemplazo utilizadas con el comando
s, suponga que NO se admiten secuencias de escape de caracteres de control , por lo que, de nuevo, incluyen caracteres de control. como literales , como arriba.- Solo Linux
sed ''s/-//t/'' <<<$''ab'' # -> ''a<tab>b'' - macOS y Linux:
sed ''s/-/''$''/t''''/'' <<<''a-b''
sed ''s/-/''"$(printf ''/t'')"''/'' <<<''a-b''
- Solo Linux
Lo mismo para los argumentos de texto para las funciones
iya: no use secuencias de caracteres de control , ver abajo.
- En las expresiones regulares (tanto en patrones para selección como en el primer argumento para la función
- Etiquetas y bifurcaciones : las etiquetas, así como el argumento nombre-etiqueta para las funciones
byt, deben ir seguidas de una nueva línea literal o un$''/n''empalmado . Alternativamente, use múltiples opciones-ey termine cada derecho después del nombre de la etiqueta.- Solo Linux
sed -n ''/a/ bLBL; d; :LBL p'' <<<$''a/nb'' # -> ''a'' - macOS y Linux:
- O BIEN (nuevas líneas reales):
sed -n ''/a/ bLBL d; :LBL p'' <<<$''a/nb'' - O (instancias empalmadas
$/n):
sed -n ''/a/ bLBL''$''/n''''d; :LBL''$''/n''''p'' <<<$''a/nb'' - O (múltiples
-eopciones):
sed -n -e ''/a/ bLBL'' -e ''d; :LBL'' -e ''p'' <<<$''a/nb''
- O BIEN (nuevas líneas reales):
- Solo Linux
- Funciones
iapara insertar / agregar texto : siga el nombre de la función por/, seguido de una nueva línea literal o un$''/n''empalmado antes de especificar el argumento de texto.- Solo Linux
sed ''1 i new first line'' <<<$''a/nb'' # -> ''new first line<nl>a<nl>b'' - macOS y Linux:
sed -e ''1 i/'$''/n''''new first line'' <<<$''a/nb'' - Nota:
- Sin
-e, el argumento de texto inexplicablemente no termina en línea nueva en la salida en macOS (¿error?). - No utilice escapes de caracteres de control como
/ny/ten el argumento de texto, ya que solo son compatibles con Linux. - Si, por lo tanto, el argumento de texto tiene nuevas líneas internas,
/-scapeelas. - Si desea colocar comandos adicionales después del argumento de texto, debe terminarlo con una nueva línea (sin escalar) (ya sea literal o empalmada) o continuar con una opción
-eseparada (este es un requisito general que se aplica a todas las versiones) .
- Sin
- Solo Linux
- Dentro de las listas de funciones (llamadas a múltiples funciones incluidas en
{...}), asegúrese de terminar también la última función, antes del cierre}, con;.- Solo Linux
-
sed -n ''1 {p;q}'' <<<$''a/nb'' # -> ''a'' - macOS y Linux:
-
sed -n ''1 {p;q;}'' <<<$''a/nb''
Las características específicas de sed GNU que faltan de BSD sed conjunto:
Características de GNU que perderás si necesitas admitir ambas plataformas:
Varias opciones de ajuste y sustitución de expresiones regulares (tanto en patrones para la selección de líneas como en el primer argumento para la función
s):- La opción
Ipara la coincidencia de expresiones regulares sensibles a mayúsculas y minúsculas (increíblemente, BSDsedno es compatible con esto en absoluto). - La opción
Mpara la coincidencia de varias líneas (donde^/$coincide con el inicio / final de cada línea ) - Para opciones adicionales que son específicas de la función
s, consulte https://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Command
- La opción
Secuencias de escape
Secuencias de escape relacionadas con la sustitución como
/uen el argumento de reemplazo de la funcións///que permite la manipulación de subcadenas , dentro de los límites; por ej.,sed ''s/^.//u&/'' <<<''dog'' # -> ''Dog''- ver http://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022 -MandoSecuencias de escape de caracteres de control: además de
/n,/t, ..., escapes basados en puntos de código; por ejemplo, todos los siguientes escapes (hex., octal, decimal) representan una sola cita (''):/x27,/o047,/d039- ver https://www.gnu.org/software/sed/manual/ sed.html # Escapes
Extensiones de direcciones , como
first~steppara hacer coincidir cada línea paso-th,addr, +Nparaaddrlíneas N después deaddr, ... - ver http://www.gnu.org/software/sed/manual/sed. html # Direcciones
[1] La versión de macOS sed es anterior a la versión de otros sistemas similares a BSD como FreeBSD y PC-BSD. Desafortunadamente, esto significa que no puede suponer que las funciones que funcionan en FreeBSD, por ejemplo, funcionarán [lo mismo] en macOS.
[2] La cadena ANSI C-cotizada $''/001/002/003/004/005/006/007/010/011/013/014/015/016/017/020/021/022/023/024/025/026/027/030/031/032/033/034/035/036/037/177'' contiene todos los caracteres de control ASCII excepto /n (y NUL), por lo que puede usarlo en combinación con [:print:] para una emulación bastante robusta de [^/n] :
''[[:print:]''$''/001/002/003/004/005/006/007/010/011/013/014/015/016/017/020/021/022/023/024/025/026/027/030/031/032/033/034/035/036/037/177'''']