MostrarApostrofos-español

Esta pregunta es tan frecuente que merece su propia respuesta. Y aunque pareciera que esto es una limitación del awk, en realidad casi siempre es culpa de la forma en como se utilizan los caracteres de citado (comillas y apóstrofos) en el shell.

En resumen

Use la secuencia de escape en base ocho ('\047') o printf ('print "%c", 39'). No use las secuencias de escape hexadecimales ('\x27') dado que podrían reaccionar negativamente con el texto lindante, dependiendo de la implementación de awk usada.

En detalle

Para mostrar el texto "dijo '¡Hola mundo!' y entonces devolvió 0", uno puede correr los siguientes programas:

BEGIN {
	print "dijo '¡Hola mundo!' y entonces devolvió 0"
	exit 0
}

Sin embargo, cuando uno intenta realizar algo similar en la consola:

awk 'BEGIN{print "dijo '¡Hola mundo!' y entonces devolvió 0";exit 0}'

...el shell se queja, dado a que intenta interpretar "¡Hola mundo!" como una cadena de parámetros para ser insertados entre dos textos agrupados con apóstrofos.

Lo primero que uno podría pensar, es agrupar el fragmento del programa en comillas en lugar de apóstrofos, pero podría dar problemas con los strings literales de awk y con el operador para referenciar campos "$", a menos que se escapen adecuadamente con contrabarras los caracteres como $, ", \, (entre otros), ofuscando bastante más el código.

Secuencias de escape hexadecimales

Desafortunadamente, la siguiente solución más obvia - especificar caracteres en hexa - parece funcionar al principio:

awk 'BEGIN{print "dijo \x27¡Hola mundo!\x27 y entonces devolvió 0";exit 0}'

...pero esto no siempre funciona. Pruebe por ejemplo el siguiente fragmento de código en gawk, mawk y en el awk de busybox y compare los resultados:

awk 'BEGIN{print "\x27foo!\x27"}'

Notese que mientras mawk y el awk del busybox dan los resultados esperados, gawk devuelve un caracter multibyte. En el párrafo 3 de la sección "Rationale" del Open Group Base Specifications issue 6 (en inglés), y reiterado en el manual de GNU awk en section 2.2 ("Secuencias de escape") (en inglés)), la notación hexadecimal '\xHH' es ambigua porque permite especificar más de dos bytes hexadecimales sucesivos. Desafortunadamente el comportamiento preciso cuando se dan más de dos bytes, depende de la implementación.

Secuencias de escape en base ocho

Por suerte siempre podemos recurrir a los cuchillos de piedra y pieles de osos: las secuencias de escape octales deben obligatoriamente tener ancho fijo.

awk 'BEGIN{print "\047foo!\047"}'

Usos y abusos de printf

O simplemente podríamos usar printf:

awk 'BEGIN{printf "%cfoo!%c\n", 39, 39}'

...pero entonces tendríamos que empezar a contar los parámetros para asegurarnos que todas las secuencias de cape tienen un número correspondiente. gawk tiene como característica una extensión de printf que permite reusar los argumentos de acuerdo a la posición especificada en la cadena de formato:

awk 'BEGIN{printf "%1$cfoo!%1$c\n", 39}'

...pero el beneficio de esto es mínimo en comparación a lo sucio termina quedando, así que mejor pretendamos no haber dicho nada.

Concatenación explícita

There is also the old fallback of putting a single quote character in its own variable and then using explicit string concatenation:

awk 'BEGIN{q="\047";print q"foo!"q}'

...pero esto es desprolijo cuando tenemos que manejar textos largos que contienen varios apóstrofos.

Haz lo correcto

La forma más prolija es simplemente escribir el programa en su propio archivo. Pueden haber formas específicas del shell para resolver este problema: siéntase libre de agregarlas a esta página si conoce alguna.