2010-07-14 12:51:58 +0000 2010-07-14 12:51:58 +0000
32
32

bash: cómo pasar argumentos de línea de comandos que contienen caracteres especiales

He escrito un programa para linux program que necesita una expresión regular como entrada.

Quiero llamar al programa en el shell bash y pasar esa expresión regular como argumento de línea de comandos al programa (también hay otros argumentos de línea de comandos). Una expresión regular típica se parece a

[abc]\_[x|y]

Desgraciadamente los caracteres [, ] y | son caracteres especiales en bash. Por lo tanto, llamar a

program [abc]\_[x|y] anotheragument

no funciona. ¿Hay alguna manera de pasar la expresión utilizando algún tipo de caracteres de escape o comillas, etc.?

(Llamar a program "[abc]\_[x|y] anotheragument" tampoco funciona, porque interpreta los dos argumentos como uno solo).

Respuestas (8)

29
29
29
2010-07-14 12:59:46 +0000

Puede

  1. Escapar cada símbolo especial con una barra invertida (como en \[abc\]_\[x\|y\]) o
  2. Comillas dobles en todo el argumento (como en "[abc]_[x|y]").

EDIT: Como han señalado algunos , la doble comilla no impide la expansión de variables ni la sustitución de comandos. Por lo tanto, si su regex contiene algo que puede ser interpretado por bash como uno de esos, use comillas simples en su lugar.

28
28
28
2011-10-21 12:19:50 +0000

Utilice comillas simples. Las comillas simples garantizan que no se interprete ninguno de los caracteres.

$ printf %s 'spaces are not interpreted away
neither are new lines
nor variable names $TESTING
nor square brackets [TESTING]
nor pipe characters or redirection symbols | > <
nor the semicolon ;
nor backslashes \a \b \c \
the only thing that does not work is the single quote itself
'

Hay dos soluciones si necesita incrustar una comilla simple:

$ printf '%s\n' '[Don'"'"'t worry, be happy!]'
[Don't worry, be happy!]
$ printf '%s\n' '[Don''t worry, be happy!]'
[Don't worry, be happy!]
6
6
6
2010-07-15 06:09:18 +0000

Por man bash

Existen tres mecanismos de entrecomillado: el carácter escape, las comillas simples y las comillas dobles.

Una barra invertida no entrecomillada ( ** ) es el carácter de escape. Conserva el valor literal del siguiente carácter, con la excepción de la barra invertida. Si aparece un par ** <newline>, y la barra invertida no está entrecomillada, el ** <newline> se trata como una continuación de línea (es decir, se elimina del flujo de entrada y se ignora efectivamente).

Al encerrar los caracteres entre comillas simples se mantiene el valor literal de cada carácter dentro de las comillas. Una comilla simple no puede aparecer entre comillas simples, incluso si va precedida de una barra invertida.

Al encerrar los caracteres entre comillas dobles se conserva el valor literal de todos los caracteres entre las comillas, con la excepción de $ , ` , ** , and, when history expansion is enabled, **!. The characters $ and ` que conservan su significado especial dentro de las comillas dobles. La barra invertida sólo conserva su significado especial cuando va seguida de uno de los siguientes caracteres: $ , ` , , \N , o . Una comilla doble puede ser citada dentro de comillas dobles precediéndola de una barra invertida. Si se activa, la expansión del historial se realizará a menos que un ! que aparezca entre comillas dobles se escape con una barra invertida. La barra invertida que precede al ! no se elimina.

Los parámetros especiales * y @ tienen un significado especial cuando aparecen entre comillas dobles (véase PARÁMETROS más adelante).

Las palabras de la forma $‘ cadena se tratan de forma especial. La palabra se expande a cadena, con los caracteres de barra invertida reemplazados según lo especificado por el estándar ANSI C. Las secuencias de escape de barra invertida, si están presentes, se decodifican como sigue:

**\a** alert (bell) **\b** backspace **\e**** \E **an escape character** \f **form feed** \n **new line** \r **carriage return** \t **horizontal tab** \v **vertical tab** \ **backslash**  

El resultado expandido está entre comillas simples, como si el signo de dólar no hubiera estado presente. 

Una cadena entre comillas dobles precedida por un signo de dólar ( **$"** _string_ **"** ) hará que la cadena se traduzca según la configuración regional actual. Si la configuración regional actual es **C** o **POSIX** , el signo de dólar se ignora. Si la cadena se traduce y se reemplaza, el reemplazo es de doble comilla. **single quote** \" **double quote** \**_nnn_ the eight-bit character whose value is the octal value _nnn_ (one to three digits)**\x**_HH_ the eight-bit character whose value is the hexadecimal value _HH_ (one or two hex digits)**\u**_HHHH_ the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value _HHHH_ (one to four hex digits)**\U**_HHHHHHHH_ the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value _HHHHHHHH_ (one to eight hex digits)**\c**_x_ a control-_x_ character

El resultado expandido está entre comillas simples, como si el signo de dólar no hubiera estado presente.

Una cadena entre comillas dobles precedida por un signo de dólar ( $” string ) hará que la cadena se traduzca según la configuración regional actual. Si la configuración regional actual es C o POSIX , el signo de dólar se ignora. Si la cadena se traduce y se reemplaza, el reemplazo es de doble comilla.

2
2
2
2010-07-15 02:11:13 +0000

Aunque no sea útil como regex, algunas secuencias de caracteres pueden ser interpretadas como nombres de variables Bash. Para evitar que esto ocurra y que se expandan, utilice comillas simples en lugar de dobles:

program '[abc]_[x|y]' anotherargument

Cita cada argumento por separado (si necesitan comillas) para que se interpreten como argumentos independientes. También puede utilizar arrays en algunos casos:

param_array=('[abc]_[x|y]' anotherargument) # create an array
param_array+=(yetanother) # append another element to the array
program "${param_array[@]}" # use the array elements as arguments to program
2
2
2
2010-07-14 12:57:29 +0000

Puede utilizar una barra invertida ( `Puede utilizar una barra invertida ( ) delante de los caracteres especiales para escaparlos de la siguiente manera

john@awesome:~ # echo 0x1& &
1
1
1
2010-07-14 12:56:05 +0000
program "[abc]_[x|y]"
program "[abc]_[x|y]" anotherargument
0
0
0
2010-07-15 07:18:57 +0000

¿De dónde viene el patrón? ¿Es fijo o de un usuario? ¿Es el usuario que invoca el script en el sistema local, o alguien remoto?

Se utilizan las comillas para envolver los datos y evitar que el shell los interprete. Hay dos opciones:

  1. Comillas dobles, que aún permiten alguna interpretación ($expand y backticks)
  2. Comillas simples, que pasan todo lo que se dice. 2. Comillas simples, que pasan todo literalmente

Debido a que $ es un carácter válido en regexps (fin de línea/buffer) probablemente quiera usar comillas simples para mantener el regexp, a menos que esté almacenando en una variable. Si está tomando datos arbitrarios de alguien que no es de confianza, necesitará reemplazar ' con '"'"' y luego envolverlo en comillas simples.

Tenga en cuenta que [abc]_[x|y] parece que quiere coincidir con x o y, mientras que en realidad está coincidiendo con uno de los tres caracteres xy|. Los corchetes coinciden con los caracteres dentro y sólo con - para los rangos y un ^ al principio para la negación. Por lo tanto, [abc]_(x|y) podría ser lo que querías decir, y los paréntesis son los caracteres que son especiales para shell. Los corchetes no son especiales para Shell, sólo parece que lo son. Los corchetes dobles [[...]] son especiales.

0
0
0
2010-07-14 12:57:13 +0000

Escaparlas debería funcionar bien:

programm \[abc\]_\[x\|y\]