Tengo un comando de reemplazo sed que me gustaría que fuera compatible tanto con BSD sed
como con GNU sed
. Las expresiones regulares extendidas no son un problema ya que no las necesito en este caso. Mi principal problema es la diferencia en la forma en que los dos sed
interpretan las secuencias de escape de caracteres en elreemplazoinstrumentos de cuerda. Mi cadena de reemplazo contiene tabulaciones y nuevas líneas y me gustaría que fueran visibles en las cadenas de comando para facilitar el mantenimiento; sin embargo, BSD sed
no interpreta las secuencias de escape y GNUsed
hace. ¿Cuál es la forma apropiada de dar instrucciones sed
para interpretar estas secuencias de escape en BSD? Los siguientes dos fragmentos resumen mi problema:
ÑUsed
echo ABC | sed 's/B/\n\tB\n'
rinde
A
B
C
BSDsed
echo ABC | sed 's/B\n\tB\n'
rendimientos
AntBnC
Claramente, \n
y \t
BSD no las interpreta como secuencias de escape.sed
Ahora, a mi pregunta. Según la sed
página de manual de BSD:
Para especificar un carácter de nueva línea en la cadena de reemplazo, precedido por una barra invertida.
¿Esto implica que necesitaría preceder a unliteral¿nueva línea por una barra invertida? ¿Cuál es la forma adecuada de dar instrucciones sed
para interpretar secuencias de escape como \n
en el texto de reemplazo?
Respuesta1
Puede utilizar las $'...'
comillas bash para interpretar los escapes antes de pasar la cadena a sed
.
Desde la página de manual de bash:
Words of the form $'string' are treated specially. The word
expands to string, with backslash-escaped characters replaced as
specified by the ANSI C standard. Backslash escape sequences, if
present, are decoded as follows:
\a alert (bell)
\b backspace
\e an escape character
\f form feed
\n new line
\r carriage return
\t horizontal tab
\v vertical tab
\\ backslash
\' single quote
\nnn the eight-bit character whose value is the octal
value nnn (one to three digits)
\xHH the eight-bit character whose value is the hexadeci-
mal value HH (one or two hex digits)
\cx a control-x character
The expanded result is single-quoted, as if the dollar sign had
not been present.
A double-quoted string preceded by a dollar sign ($) will cause
the string to be translated according to the current locale. If
the current locale is C or POSIX, the dollar sign is ignored. If
the string is translated and replaced, the replacement is double-
quoted.
Respuesta2
Si necesita escribir scripts portátiles, debe ceñirse a las funciones delestándar POSIX(también conocido como Single Unix, también conocido como Especificación básica de grupo abierto).Número 7 también conocido como POSIX-1.2008es el último, pero muchos sistemas aún no han terminado de adoptarlo.Número 6 también conocido como POSIX-1.2001es proporcionado en general por todos los unices modernos.
Ensed, el significado de secuencias de escape como \t
y \n
no es portátil, excepto que en unexpresión regular, \n
representa una nueva línea. En el texto de reemplazo de un s
comando, \n
no es portátil, pero puede usar la secuencia barra invertida-nueva línea para representar una nueva línea.
Una forma portátil de generar un carácter de tabulación (o cualquier otro carácter expresado en octal) es contr
. Almacene el carácter en una variable de shell y sustituya esta variable en el fragmento sed.
tab=$(echo | tr '\n' '\t')
escape=$(echo | tr '\n' '\033')
embolden () {
sed -e 's/^/'"$escape"'[1m/' -e 's/$/'"$escape"'[0m/'
}
Tenga en cuenta nuevamente que las nuevas líneas deben expresarse de manera diferente en las expresiones regulares y en s
los textos de reemplazo.
Es posible que desee utilizarawken cambio. Permite escapes de barra invertida, incluidos escapes octales \ooo
, en cada cadena literal.
Respuesta3
Esto ha sido respondido en Stack Overflow:
https://stackoverflow.com/questions/1421478/how-do-i-use-a-new-line-replacement-in-a-bsd-sed
Es más o menos exactamente lo que dijo jw013.
Para insertar una pestaña literal, escriba ctrl+ VTab.