Opuesto al comando `fuente`

9

Uso el sourcecomando en mi script bash para leer / imprimir los valores de las variables

more linuxmachines_mount_point.txt

export linuxmachine01="sdb sdc sdf sdd sde sdg"
export linuxmachine02="sde sdd sdb sdf sdc"
export linuxmachine03="sdb sdd sdc sde sdf"
export linuxmachine06="sdb sde sdf sdd"

source  linuxmachines_mount_point.txt

echo $linuxmachine01
sdb sdc sdf sdd sde sdg

¿Qué es lo opuesto sourcepara desarmar las variables?

Resultados previstos

echo $linuxmachine01

< no output >
yael
fuente
14
No es sourceeso lo que establece las variables en su entorno, sino las exportdeclaraciones en el archivo que usted source. Entonces, lo opuesto a sourcepodría ser source, si tiene sourceun archivo diferente que tiene unsettodas las mismas variables.
user4556274
2
yael, no uses exportaciones, solo usa name = "val". Exportar es para variables de script a binarios (el entorno).
Ctrl-D
1
Relacionado: unix.stackexchange.com/q/382618/117549
Jeff Schaller
2
Esto es imposible. El concepto que está buscando se llama Computación reversible . Los lenguajes de programación deben diseñarse específicamente con algunas restricciones severas para ser reversibles. Bash no es uno de esos lenguajes de programación.
Jörg W Mittag
1
@yael, eso no es cierto (y obviamente nunca ejecutó la prueba que le está diciendo a ctrl-d que haga); absolutamente no necesitas el exports. Todo lo que exporthace es copiar los valores en el entorno, pero están presentes como variables de shell, estén o no definidos también como variables de entorno. Además, la definición de variables de entorno innecesarias acorta la longitud máxima de la línea de comandos, ya que se almacenan en el mismo espacio (¡limitado!) Por proceso.
Charles Duffy

Respuestas:

21

Usando una subshell (Recomendado)

Ejecute el comando de origen en una subshell:

(
source linuxmachines_mount_point.txt
cmd1 $linuxmachine02
other_commands_using_variables
etc
)
echo $linuxmachine01  # Will return nothing

Subcapas se definen por parens: (...). Cualquier variable de shell establecida dentro de la subshell se olvida cuando la subshell finaliza.

Usando unset

Esto desarma cualquier variable exportada por linuxmachines_mount_point.txt:

unset $(awk -F'[ =]+' '/^export/{print $2}' linuxmachines_mount_point.txt)
  • -F'[ =]+' le dice a awk que use cualquier combinación de espacios y signos de igual como separador de campo.

  • /^export/{print $2}

    Esto le dice a awk que seleccione líneas que comiencen exporty luego imprima el segundo campo.

  • unset $(...)

    Esto ejecuta el comando dentro $(...), captura su stdout y desarma cualquier variable nombrada por su salida.

John1024
fuente
¿por qué no usar esto? para i en el archivo 'awk' {print $ 2} '| awk -F "=" '{print $ 1}' `; desarmar $ i; hecho ? (más simple para sin configurar)
yael
2
@yael Eso usa un proceso extra y un ciclo cuando ninguno de los dos es necesario. Las opiniones pueden variar, pero no lo veo más simple. También y potencialmente peligroso, se supone que cada línea filees una declaración de exportación.
John1024
8
@yael Además, desarmar variables y deshacer otros efectos secundarios del código es exactamente para qué sirven las subcapas. Lo hacen de manera simple y confiable. A menos que exista alguna razón especial, las subcapas son lo que debería usar.
John1024
4

No puedes deshacer sourceel guión.

Lo que puede hacer es almacenar todas las variables exportadas en un archivo temporal, compararlo con las variables después de obtener el script y luego eliminar el desbordamiento con unset, por ejemplo:

export > temp_file
source myscript

#... do some stuff

unset "$(comm -3 <(sort temp_file) <(export | sort) | awk -F'[ =]' '{print $3}' | tr '\n' ' ')"
jimmij
fuente
¿por qué no usar esto? para i en el archivo 'awk' {print $ 2} '| awk -F "=" '{print $ 1}' `; desarmar $ i; hecho ? (más simple para sin configurar)
yael
@yael solo funcionará si el script contiene solo exports.
jimmij
lo que quiere decir "exportación s", mi archivo incluye linuxmachine01 = "SDB SDC sdf SDD sde SDG" y así sucesivamente, y cuando se utiliza el bucle awk su desactivar la variable sin problemas
Yael
@yael No sé exactamente cómo se ve su archivo, así que le di una respuesta general, por ejemplo, qué pasa si el script contiene un comentario en la parte superior que dice "# Aquí hay algunas variables para exportar con puntos de montaje".
jimmij
2

Puede usar el unsetcomando para "olvidar" las variables.

francois P
fuente
El archivo podría estar con máquinas diff, entonces, ¿cómo desarmar las segundas variables en el archivo?
yael
Unset variablename lo olvidará (puede encontrarlo explicado en la página del manual bash / sh / ksh / zsh) demostración de este: pastebin.com/MGQyTZEA
francois P
sí, pero ya que las variables podrían ser diff, escritura del golpe necesidad de hacerlo por leer la variable del archivo y desactívala, que puedo ser estática debido variables son desconocidos
Yael
entonces el suyo grep exportar líneas (CUT) para variables de lista del archivo para ser desarmado linuxmachine06 exportación = "SDB sde sdf SDD", entonces obtendrá linuxmachine06 como un nombre para desarmar ejemplo: pastebin.com/M9eCtLc7 al ver que el comando unset aquí doen no sé el nombre de la variable, solo se conoce al final
francois P
ok usaré esta sintaxis para desarmar - para i en el archivo 'awk' {print $ 2} '| awk -F "=" '{print $ 1}' `; desarmar $ i; Done
Yael
2

La solución más simple para tener el resultado que espera (nada) es volver a declarar la variable como vacía:

$ export linuxmachine01="sdb sdc sdf sdd sde sdg"
$ echo "$linuxmachine01"
sdb sdc sdf sdd sde sdg

$ linuxmachine01=""
$ echo "$linuxmachine01"
$

Por supuesto, la variable aún está definida (y exportada), vacía pero definida:

$ declare -p linuxmachine01
declare -x linuxmachine01=""

Para eliminar correctamente la variable tanto del entorno como del shell en ejecución, debe usar unset (la forma recomendada):

$ unset linuxmachine01
$ declare -p linuxmachine01
bash: declare: linuxmachine01: not found
$ echo "$linuxmachine01"
$
Isaac
fuente
1

La forma más sencilla de hacer esto es modificar su script para que también defina un comando para deshacer el efecto del script:

export linuxmachine01="sdb sdc sdf sdd sde sdg"
export linuxmachine02="sde sdd sdb sdf sdc"
export linuxmachine03="sdb sdd sdc sde sdf"
export linuxmachine06="sdb sde sdf sdd"
alias linuxmachines_mount_point='for v in linuxmachine01 linuxmachine02 linuxmachine03 linuxmachine04; do unset $v; done; unalias linuxmachines_mount_point'
Lie Ryan
fuente
¿Por qué un alias en lugar de una función? Tenga en cuenta que los alias están deshabilitados en shells no interactivos de manera predeterminada, por lo que, desde el primer momento, esto no funcionará en un script.
Charles Duffy
... en realidad, esto sería aún más fácil si definiéramos solo una variable y, por lo tanto, solo tuviéramos que desarmar: declare -A linuxmachines=( [01]="sdb sdc sdf" [02]="sde sdd sdb" [03]="whatever" )entonces es solo unset linuxmachinesrevertir.
Charles Duffy
@CharlesDuffy: tanto el alias como la función están bien para este propósito. La razón por la que no sugiero poner todo en una variable es que definir un comando deshacer es mucho más genérico. Puede definir no solo las variables, sino también las funciones, los alias, la configuración del sistema, la configuración del terminal, etc. Proporciona una mejor abstracción ya que no tiene que preocuparse por el contenido exacto del comando deshacer.
Lie Ryan
Creo que mi punto anterior es que los alias no están bien para el propósito, si "el propósito" incluye el uso no interactivo (es decir, la invocación de los scripts).
Charles Duffy
0

Puede escribir su linuxmachines_mount_point.txt de esta manera

test "$linuxmachine01" && unset -v linuxmachine01 || linuxmachine01="sdb sdc sdf sdd sde sdg"

Cuando necesitas tus variables

source linuxmachines_mount_point.txt

Cuando quieras eliminar las variables

source linuxmachines_mount_point.txt
ctac_
fuente
0

Si está utilizando el sourcecomando para activar a VirtualEnvironment, puede salir usando el comando deactivate.

Wolf Elkan
fuente