El escape de barra invertida para una sola cita en sed produce un error

0

La intención es insertar justo después de la HEAD Código de etiqueta de Google en un sitio web HTML heredado.

#!/bin/bash

find . -type f -iname "*.php" -or -iname "*.htm" -or -iname "*.html" | while read i; do
    echo "Processing: $i"
    sed -i 's*<HEAD>*&\
<!-- Global site tag (gtag.js) - Google Analytics -->\
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-1234567-2"></script>\
<script>\
  window.dataLayer = window.dataLayer || [];\
  function gtag(){dataLayer.push(arguments);}\
  gtag('js', new Date());\
\
  gtag('config', 'UA-1234567-2');\
</script>*' "$i"

done

Lo anterior coloca el código de etiqueta de Google donde debería, pero sin las comillas simples:

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-1234567-2"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag(js, new Date());

  gtag(config, UA-1234567-2);

Las comillas simples faltan una vez procesadas:

# diff actual_google_tag_code processed
6c6
<   gtag('js', new Date());
---
>   gtag(js, new Date());
8,9c8
<   gtag('config', 'UA-1234567-2');
< </script>
---
>   gtag(config, UA-1234567-2);

Si sustituyo el ' con un \', Recibo un mensaje de error:

line 13: syntax error near unexpected token `('
line 13: `  gtag(\'js\', new Date());\'

Ya que estoy usando \ para continuar con cada línea, no estaba seguro de que la barra diagonal inversa para escapar de la comilla simple funcionara, pero pensé que lo intentaría.

¿Cómo puedo conservar esas comillas simples en el código de la etiqueta de Google?

Edward_178118
fuente
shellcheck.net muestra que su código original está horriblemente roto (aunque no sé la respuesta). Muchas advertencias "Esta barra invertida + salto de línea es literal. Salta las comillas simples si solo quieres romper la línea". porque todo está dentro de una cadena entre comillas que comienza en el sed línea.
DavidPostill
No sé si esto es portátil, pero en GNUsed podría ser con escape hexadecimal sed 's/f/\x27/' <<<foo o escape decimal sed 's/f/\d039/' <<<foo
Paulo

Respuestas:

1

Desde man 1 bash:

La inclusión de caracteres en comillas simples conserva el valor literal de cada carácter dentro de las comillas. Una sola cita puede no aparecer entre comillas simples, incluso cuando está precedida por una barra invertida.

Solución: coloque comillas simples dentro de comillas dobles:

  gtag('"'js'"', new Date());\
#      ^        - single quote was opened earlier, this character closes it
#       ^^^^^^  - these are double quotes with content, single quotes are part of the content
#             ^ - this single quote will be closed later
# Do not paste these comments into your script.

Repita este truco donde lo necesite, será como:

  gtag('"'config', 'UA-1234567-2'"');\

(recuerde que esta línea continúa con la anterior, donde ya se abre una sola cita; al final, la deja abierta para cerrarse en la siguiente línea).

En general es posible colocar solo ' en comillas dobles, dejando todo lo demás en comillas simples, por ejemplo:

echo '$A'"'"'$B'"'"'$C'
#     ^^     ^^     ^^ - in single quotes, so no variable expansion here
#         ^      ^     - in double quotes, so ' is possible

El resultado es $A'$B'$C.

Kamil Maciorowski
fuente
Intenté colocar comillas dobles alrededor de las comillas simples, pero eso resultó en que hubiera una comilla doble en lugar de una comilla simple. ¿Me estoy perdiendo de algo?
Edward_178118
gtag ('"' js '"', new Date ()); \ works y gtag ('"' config ',' UA-1234567-2 '"'); \ Simplemente me cuesta entenderlo por qué esto funciona :-)
Edward_178118
@ Edward_178118 Simplemente reemplace sus dos líneas con mis respectivas. El truco no es simplemente citar estas comillas simples; Necesita cerrar una cita antigua anterior justo antes y volver a abrir justo después. Inválido 'foo'bar' se vuelve válido 'foo'"'"'bar'.
Kamil Maciorowski
Usted dijo, "comillas simples se abrió antes". ¿Dónde está abierto antes? La primera comilla simple está en gtag ('?
Edward_178118
La primera cita simple es la de?
Edward_178118