Generando comandos con expansión variable en un bucle

Generando comandos con expansión variable en un bucle

Quiero crear alias locales mientras trabajo en determinados directorios. Por ejemplo, me gustaría tener lo siguiente en un archivo llamadolocal_alias

alias foo='bar'

Quería escribir un script de limpieza para eliminar estos alias una vez que termine de trabajar. Algo como:

egrep "alias [[:alnum:]]+" local_alias -o|while read i; do
  un$i
done

Si cambio la línea central a echo un$i, el resultado es lo que parece un unaliascomando con el formato correcto: unalias foo. Pero tal como está escrito, lo entiendo unalias: foo: not found.

Si intento citar la línea media: "un$i", obtengo unalias foo: command not found.

¿Qué estoy haciendo mal?

Respuesta1

Los alias son específicos del shell, por lo que cuando ejecuta su script de esta manera:

#!/bin/bash

...
unalias ....
...

Se ejecuta como un shell secundario, que normalmente no tendrá los mismos alias. Para agravar el problema, también estás lidiando con otro problema. Tan pronto como el script finaliza, el shell secundario cuyos alias se han eliminado desaparece, devolviéndole al shell principal que todavía tiene sus alias intactos.

No hay manera que yo sepa de modificar los alias de su shell actual de esta manera.

Entonces, ¿cómo hacer esto?

Puede construir un alias o una función dentro del alcance del shell actual para realizar esta acción.

Ejemplo

solución de alias

$ alias unalias_local='egrep "alias [[:alnum:]]+" local_alias -o|while read i; do un$i; done'

solución de función

$ function unalias_local { egrep "alias [[:alnum:]]+" local_alias -o | \
    while read i; do un$i; done; }

Problemas con lo anterior

El OP proporcionó estas soluciones a esta respuesta que, según afirmó, funcionarán en su escenario. Pero, en general, no se pueden cambiar los alias en una cadena de comandos canalizados como este porque cada canalización invoca un subshell, que no podrá tocar el shell principal. Así que volvemos al mismo problema que antes con el script.

Para solucionar esto, puede proporcionar la lista de alias como argumentos para un comando.

Ejemplo

$ alias ali1="cmd1"
$ alias ali2="cmd2"

Confirme los alias en nuestro shell:

$ alias | grep -E "ali[12]"
alias ali1='cmd1'
alias ali2='cmd2'

Contenido de local_alias:

$ cat local_alias 
alias ali1="cmd1"
alias ali2="cmd2"

Este comando analizará los nombres de los alias del archivo local_alias:

$ grep -oP "(?<=alias )([[:alnum:]]+)" local_alias
ali1
ali2

Podemos usarlo para unaliasestos alias así:

$ unalias $(grep -oP "(?<=alias )([[:alnum:]]+)" local_alias)
$

Ahora cuando confirmamos que se han ido:

$ alias | grep -E "ali[12]"
$

Respuesta2

Parece que estás ejecutando este código en un script independiente. Esto no funcionará: necesita cambiar la configuración de su shell en ejecución y no puede hacerlo desde otro proceso. Este código de limpieza debe estar en una función definida en su archivo .bashrc.

Un segundo problema es que la tubería también crea un subproceso (una subcapa). Entonces, si ejecuta este código dentro de su shell interactivo, el unaliascomando eliminará el alias, pero solo en el subshell. Necesita un enfoque diferente que no ejecute el unaliascomando en un subshell.

Hay varias soluciones, pero la más sencilla sería crear la lista de alias y luego ejecutar el unaliascomando una vez. Los nombres de alias no pueden contener caracteres especiales, por lo que dividir palabras en la lista de alias será suficiente para generar los argumentos unalias.

unalias $(egrep -o "alias [[:alnum:]]+" local_alias)

información relacionada