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.txt
O bien : utilice una cadena ANSI C-entrecomillada (
$''...''
) para empalmar en la línea nueva ($''/n''
; funciona enbash
,ksh
ozsh
):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--posix
para deshabilitar (ver a continuación).
- Advertencia: GNU
- Para usar funciones POSIX solamente :
- (ambas versiones): use solo las opciones
-n
y-e
(especialmente, no use-E
o-r
para activar el soporte para expresiones regulares extendidas ) - GNU
sed
: agregue la opción--posix
para 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 :--posix
sí 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
/n
y/t
generalmente 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-e
independiente. - 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
sed
implementa 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
-i
sin 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
-
-i
enciende sensiblemente la numeración de líneas por archivo de entrada en GNUsed
y 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-i
todas 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
sed
a 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 GNUsed
admite (a menos que se use--posix
), BSDsed
no 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 ) (GNUsed
no 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
/-E
significa 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 BSDsed
no 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
/n
y/t
:- En las expresiones regulares (tanto en patrones para selección como en el primer argumento para la función
s
), supongamos que solo/n
se 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
i
ya
: 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
b
yt
, deben ir seguidas de una nueva línea literal o un$''/n''
empalmado . Alternativamente, use múltiples opciones-e
y 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
-e
opciones):
sed -n -e ''/a/ bLBL'' -e ''d; :LBL'' -e ''p'' <<<$''a/nb''
- O BIEN (nuevas líneas reales):
- Solo Linux
- Funciones
i
a
para 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
/n
y/t
en 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
-e
separada (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
I
para la coincidencia de expresiones regulares sensibles a mayúsculas y minúsculas (increíblemente, BSDsed
no es compatible con esto en absoluto). - La opción
M
para 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
/u
en 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~step
para hacer coincidir cada línea paso-th,addr, +N
paraaddr
lí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'''']