
¿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 sed
no 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 sed
versiones pueden necesitar -r
en 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
sed
al 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