2010-07-09 11 views

Respuesta

30

String::ShellQuote, pero la mayoría de las veces esto no es necesario. Simplemente puede evitar invocar el shell mediante una programación cuidadosa. Por ejemplo, system takes a list of arguments en lugar de una cadena.

La mejor opción:

use IPC::System::Simple qw(systemx); 
systemx($command, @arguments); 

require IPC::System::Simple; 
use autodie qw(:all); 
system([@allowed_exit_values], $command, @arguments); 
+5

Sí, sólo evitar la concha completamente si es posible. –

+3

Buen trabajo respondiendo una [pregunta XY] (http://www.perlmonks.org/index.pl?node_id=542341) con la solución adecuada. :) – Ether

+0

¿Puede ayudar esto cuando necesita una redirección (por lo que no puede usar la forma de lista de invocación de sistema()) * y * argumentos de variables? p.ej. una solución al siguiente intento fallido de 'ls 'f o o'':' my $ foo =' f o o '; mi $ resultado = \ 'ls $ foo 2> &1\';'? – artfulrobot

3

Perl puede coincidir con el siguiente declarado función:

agrega comillas simples alrededor de una cadena y cotizaciones/escapa ningún comillas simples existentes

http://php.net/manual/en/function.escapeshellarg.php#function.escapeshellarg

así:

sub php_escapeshellarg { 
    my $str = @_ ? shift : $_; 
    $str =~ s/((?:^|[^\\])(?:\\\\)*)'/$1'\\''/g; 
    return "'$str'"; 
} 
+1

Esto no funciona. Considere pasar la cadena 'foo'bar' a la función. Producirá la siguiente cadena: ''foo \' bar''. Pero no puede haber comillas simples escapadas dentro de comillas simples. – josch

0

Estoy de acuerdo con @daxim. Pero hay algunas circunstancias en las que no puede usar esto como pasar un comando sobre un socket a un programa que no es perl o no tiene el módulo IPC disponible. También miré la expresión regular dada por @axeman y eso me parece un poco complejo. Podría estar equivocado, pero creo que no es necesario escapar de las barras diagonales inversas en cadenas sueltas para un comando. Por lo tanto, sólo podía hacer esto:

sub escapeshellarg { 
    my $arg = shift; 

    $arg =~ s/'/'\\''/g; 
    return "'" . $arg . "'"; 
} 

Si alguien tiene alguna razón, por qué esto puede ser inseguro, me gustaría saber. Lo he probado usando cualquier clase de engaño que se me ocurra para hacer que el shell ejecute código arbitrario, sin éxito, lo que me hace pensar que esta expresión regular es la misma que la implementación de PHP.

En la implementación de PHP, establece que todo lo que hace es: agrega comillas simples alrededor de una cadena y cita/escapa de cualquier comilla simple existente.

Que es lo único que hace esta expresión regular. ¿Pensamientos?

+2

Soy escéptico, preferiría siempre los cpantesters probados [String :: ShellQuote] (http://p3rl.org/String::ShellQuote) que se han implementado en la naturaleza durante años y tienen los informes de errores y -fixes mostrarlo a través de una expresión regular ad-hoc del usuario SO. Puede comparar su código con el suyo y descubrir lo que le falta. – daxim

+0

@daxim no son demasiado fáciles de comparar: http://api.metacpan.org/source/ROSCH/String-ShellQuote-1.04/ShellQuote.pm – dlamblin

+0

Maldición, lamenté accidentalmente su respuesta y ahora no puedo deshacerla . :( – josch

1

Esta funciona para mí en BASH:

sub escape_shell_param($) { 
    my ($par) = @_; 
    $par =~ s/'/'"'"'/g; # "escape" all single quotes 
    return "'$par'";  # single-quote entire string 
} 

Se basa en las siguientes declaraciones tomadas de la página man bash:

  1. personajes que encierran entre comillas simples preserva el valor literal de cada personaje dentro de las comillas.
  2. Es posible que una comilla simple no se produzca entre comillas simples, incluso cuando esté precedida por una barra diagonal inversa.
  3. La inclusión de caracteres entre comillas dobles conserva el valor literal de todos los caracteres dentro de las comillas, con la excepción de $, `, \ y, cuando se habilita la expansión del historial,!.

De (2.) sabemos que la barra inclinada invertida no se puede usar para escapar de los qoutes individuales, pero a partir de (3.) se da a entender que las comillas dobles conservan el valor literal de las comillas simples (es decir, escape).

También tenga en cuenta que el único propósito de las comillas es cambiar el significado de los caracteres entrecomillados (no se crean objetos de cadenas especiales o cosas similares) y después de la expansión se unen todos los caracteres literales consecutivos. Entonces, 'foo''bar' es lo mismo que foobar.

Lo que hace la función anterior es citar una sola cadena entera para que ningún carácter en ella tenga un significado especial. Sin embargo, para permitir la presencia de caracteres de comillas simples, la cadena se divide dondequiera que se encuentren dichos caracteres, y se realizan las siguientes operaciones: se finaliza la subcadena anterior ('), luego se introduce una comilla simple de comillas dobles ("'") y se inicia la siguiente subcadena ('). Es por eso que ' es reemplazado globalmente por '"'"'.

Por ejemplo (pseudocódigo):

foo'bar => 'foo' + "'" + 'bar' 
Cuestiones relacionadas