¿Cómo filtrar las comillas internas?

¿Cómo filtrar las comillas internas?

¿Es posible filtrar, es decir, poner ESC delante de las comillas internas consed,awku otra herramienta *NIX (sin Perl/python)?

Ejemplo (revisado):

$ echo label=\"123 \"456\" 789\" \"AB C\" e f gh | magic-filter
label="123 \"456\" 789\" \"AB C" e f gh

etiqueta="123 \"456\" 789" "AB C"

En otras palabras se necesita un filtro que filtre de la siguiente manera: el primero y el último"char se pasará tal cual, pero todos los demás"será reemplazado por\seguido por".

Respuesta1

Con GNU sed, que soportareemplazando todas las ocurrencias de un recuento particular

$ echo label=\"123 \"456\" 789\" \"AB C\" e f gh | 
    sed -E 's/"/\\"/2g; s/\\("[^"]*)$/\1/'
label="123 \"456\" 789\" \"AB C" e f gh

Todos "(excepto el primero ") se reemplazan \"y luego \se eliminan del último\"


Si GNU sedno está disponible, elimínelo también \del primero .\"

$ echo label=\"123 \"456\" 789\" \"AB C\" e f gh | 
    sed -E 's/"/\\"/g; s/\\"/"/; s/\\("[^"]*)$/\1/'
label="123 \"456\" 789\" \"AB C" e f gh

Nota: algunas sedversiones pueden necesitar -ren lugar de-E


Conperl

$ echo label=\"123 \"456\" 789\" \"AB C\" e f gh | 
    perl -pe 's/(^[^"]*"|"[^"]*$)(*SKIP)(*F)|"/\\"/g'
label="123 \"456\" 789\" \"AB C" e f gh

Aquí, la cadena hasta el primero "y la cadena desde el último "hasta el final de la línea sonsaltadomientras que el resto "se reemplaza con\"

Respuesta2

sedal rescate.

sed 's/"/\x1b"/g;s/\x1b"/"/;s/\(.*\)\x1b"/\1"/'

Reemplace todas las comillas con ESC"y luego vuelva a visitarlas y reemplácelas primero con solo una cita, y reemplace final con solo una cita. Explicación detallada:

  • s/"/\x1b"/g: reemplace todos los caracteres de comillas con \x1b (ESC) y comillas.

  • s/\x1b"/"/: reemplace el primer \x1b (ESC) y la combinación de comillas con comillas simples.

  • s/\(.*\)\x1b"/\1"/: reemplace la combinación final \x1b (ESC) y comillas con comillas simples

Salida de ejemplo:

$ echo label=\"123 \"456\" 789\" \"AB C\" e f gh |sed 's/"/\x1b"/g;s/\x1b"/"/;s/\(.*\)\x1b"/\1"/'|od -c
0000000   l   a   b   e   l   =   "   1   2   3     033   "   4   5   6
0000020 033   "       7   8   9 033   "     033   "   A   B       C   "
0000040       e       f       g   h  \n
0000050
$

Respuesta3

Hay una manera de obtener lo que solicita en varios pasos:
suponiendo que una variable pueda contener la cadena (la cadena no tiene comillas simples):

$ label='label=\"123 \"456\" 789\" \"AB C\" e f gh'

Podríamos cortar la parte después de \":

$ front=${label%\\\"*}
$ echo "$front"
\"123 \"456\" 789\" \"AB C

Luego elimina hasta el primero \":

$ mid=${front#*\"}
$ echo "$mid"
123 \"456\" 789\" \"AB C

Reemplazar todo \"por \e":

$ final=${mid//\\\"/\\e}
$ echo "$final"
123 \e456\e 789\e \eAB C

Y finalmente, reconstruya la cadena original y use printf para los escapes:

$ printf "label=\"${front%%\\\"*}$final\"${label#"${front}"}\n"
label="123 456 789 AB C"" e f gh

$ printf "label=\"${front%%\\\"*}$final\"${label#"${front}"}\n" | od -vAn -t x1c
  6c  61  62  65  6c  3d  22  31  32  33  20  1b  22  34  35  36
   l   a   b   e   l   =   "   1   2   3     033   "   4   5   6
  1b  22  20  37  38  39  1b  22  20  1b  22  41  42  20  43  22
 033   "       7   8   9 033   "     033   "   A   B       C   "
  22  20  65  20  66  20  67  68  0a
   "       e       f       g   h  \n

información relacionada