Respuesta corta: ver BashAQ # 50: Estoy tratando de poner un comando en una variable, ¡pero los casos complejos siempre fallan! .
Respuesta larga: es debido al orden en que bash analiza la línea de comando. Específicamente, busca cosas como tuberías y redirecciones antes de expandir los valores variables, y no retrocede y vuelve a buscar tuberías, etc. en los valores expandidos. Esencialmente, las variables se sustituyen aproximadamente a la mitad del proceso de análisis, por lo que el valor solo se analiza a la mitad antes de ejecutarse.
Para resolver esto, necesita responder la pregunta de @ slhck: ¿por qué el comando se almacena en una variable en primer lugar? ¿Cuál es el problema real que estás tratando de resolver? Dependiendo del objetivo real, hay una serie de soluciones posibles:
No lo almacene en una variable, solo ejecútelo directamente. El almacenamiento de comandos para su uso posterior es complicado, y si realmente no lo necesita, simplemente no lo haga.
Usa una función en lugar de una variable. Para eso son, después de todo:
i() { cat -nT index.php |grep 'someregex'; }
i
La principal desventaja de esto es que no puede crear la función dinámicamente, no puede incluir o excluir condicionalmente el código de la función (aunque la función en sí puede tener elementos condicionales que se seleccionan cuando se ejecuta).
Utilizar eval
. Esto debe considerarse un último recurso, ya que es fácil tener un comportamiento inesperado. Básicamente, ejecuta el comando a través de otro pase de análisis completo, por lo que todas las canalizaciones, etc. obtienen su significado completo, pero también significa que las partes del comando que pensaste que eran solo datos también se analizarán y tal vez se ejecuten. Los nombres de archivo que contienen metacaracteres de shell (canalización, punto y coma, comillas / apóstrofes, etc.) pueden tener efectos extraños y, a veces, peligrosos. Si usas eval
, al menos doble-comente la cadena, de lo contrario su contenido esencialmente se analiza una vez y media, con resultados aún más extraños.
i="cat -nT index.php |grep 'someregex'"
eval "$i"
EDITAR: Otro enfoque estándar de almacenar una orden de una variable es usar una matriz en lugar de una variable simple. Esto le permite almacenar un comando con argumentos complejos (por ejemplo, que contienen espacios) sin problemas, pero no almacenará elementos como tuberías y redirecciones. Por lo tanto, el enfoque de matriz no será útil en este caso particular.