¿Cómo usar un personaje especial como uno normal?

13

Muchas preguntas como '¿Cómo escribir el carácter de comillas dobles (")?' se nos pregunta y no queremos saturar a nuestra comunidad con la misma respuesta (escríbala como \"si no estuviera incluida en 's, "si está incluida en 's). Entonces, la pregunta está aquí.

No puede escribir caracteres especiales en un terminal como los normales, por ejemplo, este comando fallará:

echo Updates (11)

Entonces, ¿cómo escribir estos caracteres en la terminal como si fueran normales?

!#$^&*?[](){}<>~;'"\|<space><tab><newline>
EKons
fuente
No hay un shell de Unix que sepa donde el retorno de carro es especial. =, @y %son especiales en algunos shells en algunos contextos.
Stéphane Chazelas
@ StéphaneChazelas Umm ... el retorno de carro ( ^M) actúa como avance de línea ( ^J) para mí (Ubuntu 14.04, sh).
EKons
No, sus transformadas de controlador del terminal ^Ma ^Jde entrada, pero ^Mno es especial para el shell y no necesita citados. Escriba echo ^V^M | hdy verá el carácter 0d (y el 0a agregado por echo).
Stéphane Chazelas
@ StéphaneChazelas Umm ... No sé qué hdes, tal vez xxdsea ​​mejor como un visor hexadecimal.
EKons
Cualquier. Utilice POSIX od -tx1o sed -n lvim's xxd si no tiene hd. Algunos sistemas también tienen cat -vteocat -A
Stéphane Chazelas

Respuestas:

26

Eso depende mucho de la cáscara. Consulte el manual de su shell para más detalles.

También tenga en cuenta que algunos caracteres solo son especiales en algunos contextos. Por ejemplo, en la mayoría de los shells, *y ?solo son especiales en contextos de listas, en POSIX o shells similares a csh, ~solo es especial al comienzo de una palabra o después de algunos caracteres como :. Lo mismo para =adentro zsh. En algunos shells, [solo es especial cuando se combina (con algunas restricciones) con a ].

En algunos shells como basho yash, los caracteres especiales como los delimitadores de tokens en blanco también varían con la configuración regional.

Los operadores de comillas (para eliminar el significado especial de esos caracteres) también varían mucho entre los shells.

Conchas tipo Bourne

Un resumen de los shells tipo Bourne (es decir, los shells que se sabe que se han llamado shen algún sistema u otro desde los años 80):

Concha Bourne

Caracteres especiales:

  • "\'&|;()^`<>$, space, newline y tab son especiales en líneas de comando simples cuando no se citan.
  • #(excepto en la versión anterior) es especial al comienzo de una línea o después de un espacio, tabulación o &|()^<>;`.
  • {y }solo son especiales porque son palabras clave de shell (por lo tanto, solo palabras en posición de comando).
  • *?[son especiales como operadores globales, por lo que solo en contextos de lista. En el caso de [, [...]es el operador globbing, ya sea [o ]solo necesita ser citado para eliminar el significado especial.
  • =es especial cuando se trata de contextos donde se trata como un operador de asignación. Es decir, en un comando simple, para todas las palabras que no siguen un argumento (excepto después set -k).

Operadores de cotizaciones

  • \cita todos los caracteres especiales excepto la nueva línea ( \<newline>es una forma de continuar una línea lógica larga en la siguiente línea física , de modo que se elimina esa secuencia). Tenga en cuenta que los backticks agregan complejidad adicional ya que dentro de ellos, \se utilizan primero para escapar del cierre de backtick y ayudar al analizador. Dentro de las comillas dobles, \solo se puede usar para escapar ", $y `( \<newline>sigue siendo una continuación de línea). Dentro de un documento aquí, igual excepto ". \es la única forma de escapar de los personajes dentro de los documentos aquí.
  • "..."las comillas dobles escapan a todos los caracteres excepto a sí mismo \, $y `.
  • '...' las comillas simples escapan a todos los caracteres menos a sí mismo.

POSIX conchas

Los shells POSIX se comportan principalmente como el shell Bourne, excepto que:

ksh

como POSIX excepto que:

  • {string}es especial si la cadena contiene una sin comillas ,(o ..en algunos casos y con algunas versiones).
  • ksh93 tiene un operador de cotización especial adicional: $'...'con reglas complejas. Ese operador se encuentra también (con algunas variaciones) en bash, zsh, mkshy FreeBSD y busybox sh.
  • ksh93también tiene un $"..."operador de cotización que funciona como, "..."excepto que la cadena está sujeta a localización (podría configurarse para que se traduzca al idioma del usuario). mkshignora el $en $"...".

bash

como ksh93pero:

  • En las configuraciones regionales de caracteres de un solo byte, todos los caracteres en blanco (según la configuración regional) se consideran delimitadores (como espacio o tabulación). En efecto, eso significa que debe citar todos los bytes con el octavo bit establecido en caso de que puedan ser un carácter en blanco en algún entorno local.
  • Cuando la expansión del historial de csh está habilitada, como en las instancias interactivas, !es especial en algunos contextos y las comillas dobles no siempre se le escapan. Y ^es especial al comienzo de un comando.

zsh

como ksh93pero:

  • misma nota que para la bashexpansión del historial de csh
  • =es especial como el primer caracter de una palabra (se =lsexpande a /bin/ls).
  • {y }también puede abrir y cerrar grupos de comandos cuando no están delimitados (como en {echo text}trabajos como el de Bourne { echo text;}).
  • excepto [solo, [necesidades citadas incluso si no se cierra con un ].
  • Con la extendedglobopción activada, #, ^y ~son comodines operadores.
  • Con la bracecclopción, {non-empty-string}es especial.
  • $"..." no es apoyado.
  • como peculiaridad especial, ?no es especial cuando se sigue un %(incluso citado o expandido) al comienzo de una palabra (para permitir la %?nameespecificación del trabajo)
  • una rcquotesopción (no habilitada por defecto) le permite a uno ingresar comillas simples como ''dentro de comillas simples à la rc(ver más abajo).

yash

como POSIXexcepto eso.

  • Todos los caracteres en blanco se consideran delimitadores.
  • Con la brace-expandopción, implementa la expansión de llaves de estilo zsh.

Para todos los shells, hay algunos contextos especiales donde las citas funcionan de manera diferente. Ya hemos mencionado aquí documentos y backticks, pero también hay [[...]]en ksh y algunos otros shells, POSIX $((...)), caseconstrucciones ...

También tenga en cuenta que las citas pueden tener otros efectos secundarios cuando se trata de expansiones (con comillas dobles), o cuando se aplican a los delimitadores de documentos aquí. También deshabilita palabras reservadas y afecta la expansión de alias.

Resumen

En los shells tipo Bourne !#$^&*?[(){}<>~;'"`\|=, SPC, TAB, NEWLINE y algunos bytes con el conjunto de 8 bits son o pueden ser especiales (al menos en algunos contextos).

Para eliminar el significado especial para que sean tratados literalmente, utilice comillas.

Utilizar:

  • '...' para eliminar el significado especial de cada personaje:

    printf '%s\n' '\/\/ Those $quoted$ strings are passed literally as
    single arguments (without the enclosing quotes) to `printf`'
  • \ para eliminar el significado especial de un solo carácter:

    printf '<%s>\n' foo bar\ baz #comment

    Arriba, solo el carácter de espacio precedido por a \se pasa literalmente a printf. Los otros son tratados por el shell como delimitadores de token.

  • utilizar "..."citar caracteres sin impedir la expansión de parámetros ( $var, $#, ${foo#bar}...), expansión aritmética ( $((1+1))también $[1+1]en algunas conchas) y la sustitución de comandos ( $(...)o la forma de edad `...`. En realidad, la mayoría de las veces, lo hace desea poner esas expansiones en el interior comillas dobles en cualquier caso . Puede usar \dentro "..."para eliminar el significado especial de los caracteres que aún son especiales (pero solo ellos).
  • Si la cadena contiene 'caracteres, todavía se puede utilizar '...'para el descanso y utilizar otros mecanismos de cotización que se pueden citar 'como "'"o \'o (si está disponible) $'\'':

    echo 'This is "tricky", isn'\''t it?'
  • Use la $(...)forma moderna de sustitución de comandos. Solo use el viejo `...`para compatibilidad con el shell Bourne, es decir, para un sistema muy viejo, y solo en asignaciones variables, como en no usar:

    echo "`echo "foo bar"`"

    Que no funcionará con el shell Bourne o las versiones AT&T de ksh. O:

    echo "`echo \"foo bar\"`"

    Que funcionará con Bourne y AT&T ksh, pero no con yash, pero usa:

    var=`echo "foo bar"`; echo "$var"

    que funcionará con todos.

    Anidarlos de forma portátil con comillas dobles también es imposible, así que de nuevo, use variables. También tenga cuidado con el procesamiento especial de barra invertida:

    var=`printf '%s\n' '\\'`

    Almacenará solo una barra invertida en el interior $var, porque hay un nivel adicional de procesamiento de barra invertida (para \, `y $(y también "cuando se cita excepto en yash)) dentro de las barras de retroceso, por lo que necesita

    var=`printf '%s\n' '\\\\'`

    o

    var=`printf '%s\n' '\\\'

    en lugar.

Familia csh

csh y tcsh tienen una sintaxis significativamente diferente, aunque todavía hay mucho en común con el shell Bourne, ya que comparten una herencia común.

Caracteres especiales:

  • "\'&|;()^`<>$, space, newline y tab son especiales en todas partes cuando no se citan.
  • #(csh es el shell que se introdujo #como líder de comentarios) es especial al comienzo de un script o después de un espacio, tabulación o nueva línea sin comillas.
  • *?[ son especiales como operadores globales, por lo que en contextos de lista
  • {non-empty-string} es especial (csh es el shell que introdujo la expansión de llaves).
  • !y ^son especiales como parte de la expansión de la historia (de nuevo, una invención csh), y las reglas de citas son especiales.
  • ~ (la expansión de tilde también es una invención de csh) es especial en algunos contextos.

Operadores de cotizaciones

Son los mismos que para el shell Bourne, pero el comportamiento difiere. tcsh se comporta como csh desde el punto de vista de la sintaxis, encontrará que muchas versiones de csh tienen errores desagradables. Obtenga la última versión de tcsh para obtener una versión más o menos funcional de csh.

  • \escapa a un solo carácter, excepto la nueva línea (igual que para el shell Bourne). Es el único operador de citas que puede escapar !. \<newline>no se escapa, pero lo transforma de un separador de comandos a un separador de tokens (como el espacio)
  • "..."escapa todos los caracteres excepto a sí misma, $, `, nueva línea y !. Contrariamente al shell Bourne, no puede usar \para escapar $y `adentro "...", pero puede usar \para escapar !o nueva línea (pero no en sí mismo, excepto cuando antes de una !o nueva línea). Un literal !es "\!"y un literal \!es "\\!".
  • '...' escapa a todos los caracteres excepto a sí mismo !y a la nueva línea. Al igual que para las comillas dobles, !y la nueva línea se puede escapar con una barra diagonal inversa.
  • la sustitución de comandos solo se realiza a través de la `...`sintaxis y difícilmente se puede usar de manera confiable.
  • La sustitución de variables también está bastante mal diseñada y es propensa a errores. Un $var:qoperador ayuda a escribir código más confiable que involucra variables.

Resumen

Manténgase alejado de csh si puede. Si no puedes usar:

  • comillas simples para citar la mayoría de los personajes. !y Newline todavía necesita a \.
  • \ puede escapar de la mayoría de los personajes
  • "..."puede permitir algunas expansiones dentro de él, pero eso es bastante defectuoso si incrustan caracteres de nueva línea y / o barra diagonal inversa, lo mejor es usar comillas simples y $var:qpara expansión variable. Tendrá que usar bucles si desea unir elementos de una matriz de manera confiable.

rc familia

rces el plan9shell y tiene gusto de sus descendientes esy akangase ha portado a Unix y me gusta de Unix. Es un shell con una sintaxis mucho más limpia y mejor y la que todos usarían si no estuviéramos atascados con los shells tipo Bourne para una compatibilidad con versiones anteriores.

rc/ /akanga

Caracteres especiales

  • #;&|^$=`'{}()<>, SPC, TAB y NEWLINE siempre son especiales cuando no se citan.
  • *?[ son operadores obsesivos.

Operador de cotización

'...'es el único operador de cotización. Se 'escribe un literal con ''comillas simples como en:

 echo 'it''s so simple isn''t it?'

es

espodría verse como un shell experimental basado en rc.

Sin embargo, tiene algunas diferencias. El de interés para este Q / A es que \también es un operador de comillas (que cita todos los caracteres especiales excepto la nueva línea) y también se puede usar para introducir secuencias de escape como \npara nueva línea, \bpara barra invertida ...

pescado

El pez es un recién llegado (circa 2005), está destinado principalmente para uso interactivo y también tiene una sintaxis significativamente diferente de otras conchas.

caracteres especiales

  • "'\()$%{}^<>;&|siempre especial cuando no se cita (tenga en cuenta el %(para expansión pid) como una diferencia significativa de otros shells, y `no es especial)
  • # (comentario) especial cuando se sigue un espacio sin comillas, tabulación, nueva línea o ;&|^<>
  • *?(pero no [...]) operadores globales

Operadores de cotizaciones

  • \cita un solo carácter especial, excepto la nueva línea, pero tenga en cuenta que también funciona como un introductor de secuencia de escape C ( \n, \b...). IOW, \nno es una cita nsino una nueva línea.
  • "..."cita todo menos a sí mismo, $y la barra invertida y la barra invertida pueden usarse para escapar de ellas. \<newline>es una continuación de línea (eliminada) dentro "...".
  • '...'cita todo menos a sí mismo y \puede usar la barra invertida para escapar de ellos.
Stéphane Chazelas
fuente
He incluido solo los especiales en todos los contextos (de modo que cactúa de la misma manera \c, cno se c: command not foundgenera en STDERR, etc.) Y estoy hablando shaquí. Además, recuerde que esta es una pregunta de "limpieza", es decir, está aquí para cubrir todos esos caracteres, por lo que no se tendrán que hacer más de 19 preguntas. La pregunta se publicó gracias a un incidente en el que se hacen diferentes preguntas para diferentes personajes, ¡seguramente queremos limpiar aquí!
EKons
Bueno, ?[son operadores globales, pero no es especial en todos los contextos, pero *parece serlo, porque es un echo *mal echocontenido del directorio actual (sin escapar de nada). echo ?hace eco de un literal ?y echo [hace eco de un literal [. Además, ]es un orador obsesivo también.
EKons
1
@ ΈρικΚωνσταντόπουλος, a *medida que un globo se expande a todos los archivos ?no ocultos, [a-z]a archivos de un solo carácter no ocultos, a archivos cuyo nombre es un solo carácter entre a y z, etc. Cuando no coinciden con ningún archivo (como en su caso ?), dependiendo del shell, obtiene un error de no coincidencia o el patrón se expande a sí mismo. En cualquier caso, incluso en el shell donde se expanden, necesitan ser citados en caso de que puedan coincidir con un archivo.
Stéphane Chazelas
Pero, no como un pegote, *todavía se expande a algo.
EKons
@ ΈρικΚωνσταντόπουλος, *es como ?, si no coincide (solo en el caso de que *solo haya archivos ocultos en el directorio actual, ya a*que no hay ningún archivo cuyo nombre comience por a...), o bien se expande a en sí (la mayoría de Bourne-como conchas), o sube un error de no coincidencia ( csh, tcsh, fish(advertencia), zsh, bash -O failglob, los primeros comandos Unix), (o se expande para nada con la opción nullglob de algunas conchas o si hay otro patrón que se expande a algo en csh, tcsh, zsh -o cshnullglob, primeros shells de Unix).
Stéphane Chazelas
4

1. Escape

Escape de todos estos caracteres con un \, como este (no funciona en líneas nuevas / retornos de carro):

$ echo Use a \"\\\" symbol to escape characters.
Use a "\" symbol to escape characters.

2. Comillas dobles

Encierre todo el texto en "s, así:

$ var=variables;echo "Enclose text in \"s. You can also use $var in them. `echo Surprise!!!`"
Enclose text in "s. You can also use variables in them. Surprise!!!

3. Comillas simples

Igual que la comilla doble, pero no hay token especial.

$ proof=proveit;echo 'This should not read "proveit": $proof'
This should not read "proveit": $proof
EKons
fuente
1
Estás describiendo el comportamiento del fishshell, no los de Bourne, donde la comilla simple cita a cada personaje (la barra invertida no es especial '...'). Tenga en cuenta que en fish, %también es un personaje especial.
Stéphane Chazelas
@ StéphaneChazelas No sé cómo fishfunciona, pero mi experiencia es que, en sh, echo '\\'ecos \ y echo '\''ecos '.
EKons
1
echo '\\'salidas \ porque echoexpande las secuencias de escape ANSI C (algunas echoimplementaciones lo necesitan echo -e '\\'). printf '%s\n' '\\'salidas \\.
Stéphane Chazelas
Tenga en cuenta que shno identifica un shell particular, hay y ha habido muchos shells diferentes y, a menudo, incompatibles sh.
Stéphane Chazelas
@ StéphaneChazelas Oh, está bien, voy a cambiar eso ahora. Por cierto, ¿hay \'un token especial dentro de una secuencia de caracteres entre comillas simples?
EKons