Tengo una lista de cadenas y quiero pasar esas cadenas como argumentos en una sola llamada de línea de comando Bash. Para cadenas alfanuméricas simples basta con simplemente pasarlos textualmente:¿Cómo puedo escapar de una cadena arbitraria para utilizarla como un argumento de línea de comando en Bash?
> script.pl foo bar baz yes no
foo
bar
baz
yes
no
entiendo que si un argumento contiene espacios o barras invertidas o comillas dobles, necesito barra invertida-escapar de las comillas dobles y las barras invertidas, y luego doblar -quitar el argumento.
> script.pl foo bar baz "\"yes\"\\\"no\""
foo
bar
baz
"yes"\"no"
Pero cuando un argumento contiene un signo de exclamación, esto sucede:
> script.pl !foo
-bash: !foo: event not found
citando doble no funciona:
> script.pl "!foo"
-bash: !foo: event not found
Tampoco se da cuenta de barra invertida-escape (cómo el literal barra invertida está presente en la salida):
> script.pl "\!foo"
\!foo
Aún no sé mucho sobre Bash, pero sé que hay otros personajes especiales que hacen cosas similares. ¿Cuál es el procedimiento general para escaparse con seguridad de una cadena arbitraria para utilizarla como un argumento de línea de comando en Bash? Supongamos que la cadena puede tener una longitud arbitraria y contener combinaciones arbitrarias de caracteres especiales. Me gustaría una subrutina escape()
que puedo usar de la siguiente manera (Perl ejemplo):
$cmd = join " ", map { escape($_); } @args;
Estos son algunos más cadenas ejemplo que debe ser escaparon con seguridad por esta función (Sé que algunos de éstos se ven similar a Windows, eso es deliberada):
yes
no
Hello, world [string with a comma and space in it]
C:\Program Files\ [path with backslashes and a space in it]
" [i.e. a double-quote]
\ [backslash]
\\ [two backslashes]
\\\ [three backslashes]
\\\\ [four backslashes]
\\\\\ [five backslashes]
"\ [double-quote, backslash]
"\T [double-quote, backslash, T]
"\\T [double-quote, backslash, backslash, T]
!1
!A
"!\/'" [double-quote, exclamation, backslash, forward slash, apostrophe, double quote]
"Jeff's!" [double-quote, J, e, f, f, apostrophe, s, exclamation, double quote]
$PATH
%PATH%
&
<>|&^
*@[email protected]#?-_
EDIT:
Sería esto el truco? Escape a cada carácter inusual con una barra diagonal inversa, y omita comillas simples o dobles. (El ejemplo está en Perl, pero cualquier idioma puede hacerlo)
sub escape {
$_[0] =~ s/([^a-zA-Z0-9_])/\\$1/g;
return $_[0];
}
Una respuesta bastante buena está aquí: http: //unix.stackexchange.com/q/4770/5779 –
El script de Perl proporcionado (en la edición) es incorrecto. Falla para líneas nuevas, que cuando escapan con una barra invertida son simplemente ignoradas. –