osx sed gnu bsd

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í:

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 en bash , ksh o zsh ):

    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).
  • 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.

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.
    • -i enciende sensiblemente la numeración de líneas por archivo de entrada en GNU sed y versiones recientes de BSD sed (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.
  • Características comunes :
    • Si restringe sus scripts sed a lo que soporta BSD sed , generalmente funcionarán también en GNU sed , 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.

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 GNU sed admite (a menos que se use --posix ), BSD sed 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 ) (GNU sed no documenta -E , pero funciona allí como un alias de -r ; versión más reciente de BSD sed , 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 BSD sed no las admite en expresiones regulares extendidas (pero, curiosamente, lo hace en los básicos , donde están ordenados por POSIX).
  • 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 usando printf (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
    • 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''
    • Lo mismo para los argumentos de texto para las funciones i y a : no use secuencias de caracteres de control , ver abajo.

  • Etiquetas y bifurcaciones : las etiquetas, así como el argumento nombre-etiqueta para las funciones b y t , 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''
  • 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) .
  • 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, BSD sed 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
  • Secuencias de escape

  • Extensiones de direcciones , como first~step para hacer coincidir cada línea paso-th, addr, +N para addr líneas N después de addr , ... - 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'''']