scripts script programas pasar parametros manejo ejemplos comando cadenas perl bash

perl - programas - script linux ejemplos



¿Cómo puedo escapar de una cadena arbitraria para utilizarla como un argumento de línea de comando en Bash? (7)

¿Cuál es el procedimiento general para escaparse con seguridad de una cadena arbitraria para utilizarla como argumento de línea de comando en Bash?

Reemplace cada aparición de '' con ''/''' , luego ponga '' al principio y al final.

Todos los caracteres a excepción de una comilla simple se pueden usar textualmente en una cadena delimitada por comillas simples. No hay forma de poner una sola comilla dentro de una cadena delimitada por comillas simples, pero eso es bastante fácil de solucionar: termine la cadena ( '' ), luego agregue una comilla simple usando una barra invertida para escapar de ella ( /' ), luego comienza una nueva cadena ( '' ).

Hasta donde yo sé, esto siempre funcionará, sin excepciones.

Tengo una lista de cadenas y quiero pasar esas cadenas como argumentos en una sola llamada de línea de comandos de Bash. Para cadenas alfanuméricas simples basta con pasarlas textualmente:

> script.pl foo bar baz yes no foo bar baz yes no

Entiendo que si un argumento contiene espacios o barras diagonales inversas o comillas dobles, necesito hacer una barra diagonal inversa-escapar de las comillas dobles y barras diagonales inversas, y luego citar dos veces el argumento.

> script.pl foo bar baz "/"yes/"///"no/"" foo bar baz "yes"/"no"

Pero cuando una discusión contiene un signo de exclamación, sucede esto:

> script.pl !foo -bash: !foo: event not found

La cita doble no funciona:

> script.pl "!foo" -bash: !foo: event not found

Tampoco lo hace el backslash-escaping (observe cómo la barra invertida literal está presente en el resultado):

> 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 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 pueda usar como a continuación (ejemplo de Perl):

$cmd = join " ", map { escape($_); } @args;

Aquí hay algunas cadenas de ejemplos más que deberían ser escapadas de forma segura por esta función (sé que algunas de ellas se ven como Windows, eso es deliberado):

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% & <>|&^ *@$$A$@#?-_

EDITAR:

¿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]; }


Bash interpreta los signos de admiración solo en modo interactivo.

Puedes evitar esto haciendo:

set +o histexpand

Dentro de las comillas dobles debe escapar de los signos de dólar, comillas dobles, barras invertidas y yo diría que eso es todo.


Cuando vea que no obtiene el resultado deseado, use el siguiente método:

"""/special character"""

donde el personaje especial puede incluir ! " * ^ % $ # @ ! " * ^ % $ # @ ....

Por ejemplo, si desea crear un bash que genere otro archivo bash en el que hay una cadena y desea asignarle un valor, puede tener el siguiente escenario de muestra:

Area="(1250,600),(1400,750)" printf "SubArea="""/""""${Area}"""/""""/n" > test.sh printf "echo """/$"""{SubArea}" >> test.sh

Entonces el archivo test.sh tendrá el siguiente código:

SubArea="(1250,600),(1400,750)" echo ${SubArea}

Como recordatorio de tener newline /n , debemos usar printf .


Esta no es una respuesta completa, pero a veces me resulta útil combinar dos tipos de comillas para una sola cadena concatenandolas, por ejemplo echo "$HOME"''/foo!?.*'' .


Puede usar comillas simples para escapar de cadenas para Bash. Sin embargo, tenga en cuenta que esto no expande las variables entre comillas como lo hacen las comillas dobles. En tu ejemplo, lo siguiente debería funcionar:

script.pl ''!foo''

De Perl, esto depende de la función que está utilizando para engendrar el proceso externo. Por ejemplo, si usa la función del system , puede pasar los argumentos como parámetros para que no haya necesidad de escapar de ellos. Por supuesto, todavía necesita escapar las comillas para Perl:

system("/usr/bin/rm", "-fr", "/tmp/CGI_test", "/var/tmp/CGI");


Si desea citar de forma segura cualquier cosa para Bash, puede usar su formato integrado printf %q :

cat strings.txt :

yes no Hello, world C:/Program Files/ " / // /// //// ///// "/ "/T "//T !1 !A "!//''" "Jeff''s!" $PATH %PATH% & <>|&^ *@$$A$@#?-_

cat quote.sh :

#!/bin/bash while IFS= read -r -d $''/n'' do printf %q "$REPLY" printf ''/n'' done < strings.txt

./quote.sh :

yes no Hello/,/ world C://Program/ Files// /" // //// ////// //////// ////////// /"// /"//T /"////T /!1 /!A /"/!////'/" /"Jeff/'s/!/" /$PATH %PATH% /& /</>/|/&/^ /*@/$/$A/$@#/?-_

Estas cadenas se pueden copiar textualmente para, por ejemplo, echo para dar salida a las cadenas originales en strings.txt.


sub text_to_shell_lit(_) { return $_[0] if $_[0] =~ /^[a-zA-Z0-9_/-]+/z/; my $s = $_[0]; $s =~ s/''/''//'''/g; return "''$s''"; }

Vea esta post anterior para un ejemplo.