Hay variables en la cáscara como $0
, $1
, $2
, $?
, etc.
Traté de imprimir las variables de shell y el medio ambiente mediante el siguiente comando:
set
Pero estas variables no estaban en la lista.
Básicamente, estas variables no se consideran variables de shell / entorno, ¿verdad? (aunque para generarlos, debe precederlos con un $
, como lo hace con las variables de shell / entorno)
export 3
convertirse$3
en una variable de entorno. No puedesunset 3
; y no puede asignar$3
un nuevo valor usando3=val
.Respuestas:
Las variables son una de las tres variedades distintas de parámetros en shell.
_
o una letra, seguido de cero o más letras, números o_
.$1
,$2
, ...$0
, todos ellos son diferentes signos de puntuación.set
sólo se muestra las variables de la cáscara.Un subconjunto de las variables de shell son las variables de entorno, cuyos valores se heredan del entorno cuando se inicia el shell o se crean estableciendo
export
atributo en un nombre válido.fuente
set
muestra todos los parámetros enzsh
(no $ 1, $ 2 ... pero $ *, $ @) y las funciones en bash y bosh. Algunos shells como ksh93 y versiones anteriores de env envían resultados de salida que no se asignaron a variables de shell. (env 1=foo ksh -c set
imprimiría1=foo
)Variables de entorno vs Parámetros posicionales
Antes de comenzar a analizar el
$INTEGER
tipo de variables, debemos comprender cuáles son realmente y cómo difieren de las variables de entorno. Variables como$INTEGER
las denominadas parámetros posicionales. Esto se describe en el estándar POSIX (Interfaz del sistema operativo portátil), sección 2.1 (énfasis mío):Por el contrario, variables como
$HOME
y$PATH
son variables de entorno. Su definición se describe en la sección 8 de la norma. :Observe su descripción. Los parámetros posicionales están destinados a aparecer en frente de un comando, es decir
command positional_arg_1 positional_arg_2...
. Ellos están destinados a ser proporcionada por el usuario para contar lo que específicamente comando a hacer. Cuando lo hagaecho 'Hello' 'World'
, imprimirá las cadenasHello
yWorld
, porque estos son parámetros posicionales paraecho
las cosas sobre las que deseaecho
operar. Yecho
está construido de tal manera que entiende los parámetros posicionales como cadenas para imprimir (a menos que sean uno de los indicadores opcionales como-n
). Si lo hace con diferentes comandos que podría no entender quéHello
yWorld
es porque tal vez espera un número. Observe que los parámetros posicionales no se "heredan": un proceso secundario no conoce los parámetros posicionales del padre a menos que se pase explícitamente al proceso secundario. A menudo se ve parámetros posicionales que se pasa con los scripts de envoltura - los que tal vez comprueban por ejemplo ya existente de un comando o añadir parámetros de posición adicionales para el comando real que se llama.Por el contrario, las variables de entorno están destinadas a afectar múltiples programas. Son entorno de variables, porque están fuera del conjunto del programa en sí (más sobre esto más adelante). Ciertas variables de entorno como
HOME
oPATH
tienen formato específico, significado específico, y significarán lo mismo para cada programa.HOME
variable significa igual a cualquiera de utilidad externa como/usr/bin/find
o su shell (y por consiguiente a una secuencia de comandos) - es el directorio inicial del nombre de usuario bajo el que se ejecuta el proceso. Tenga en cuenta que las variables ambientales se pueden utilizar para dar cuenta de la conducta comando específico, por ejemplo,UID
La variable de entorno se puede utilizar para verificar si el script se ejecuta con privilegios de root o no y se ramifica a acciones específicas en consecuencia. Las variables de entorno son heredables - procesos hijos reciben copia del entorno de los padres. Véase también Si los procesos heredan el entorno del padre, ¿por qué necesitamos exportar?En resumen, la principal distinción es que las variables de entorno se establecen fuera del comando y no están destinadas a ser variadas (generalmente), mientras que los parámetros posicionales son cosas que el comando debe procesar y cambiar.
No solo conceptos de shell
Lo que me he dado cuenta de los comentarios es que se está mezclando terminal y concha, y que se lo recomendaría leer acerca de los terminales reales que en otro tiempo eran dispositivos físicos. Hoy en día, el "terminal" al que normalmente nos referimos, esa ventana con fondo negro y texto verde es en realidad software, un proceso. Terminal es un programa que se ejecuta una concha, mientras que la cáscara es también un programa, sino el que lee lo que se escribe en la ejecución (es decir, si se trata de shell interactivo; conchas no interactivas son secuencias de comandos y
sh -c 'echo foo'
tipos de invocaciones). Más sobre cáscaras de aquí .Esta es una distinción importante, pero también es importante reconocer que el terminal es un programa y, por lo tanto, se adhiere a las mismas reglas de entorno y parámetros posicionales. Tu
gnome-terminal
cuando se inicia se verá en suSHELL
variable de entorno, y generar el shell por defecto apropiado para usted, a menos que se especifique algún otro comando con-e
. Digamos que cambié mi shell predeterminado aksh
- gnome-terminal se generará enksh
lugar debash
. Ese también es un ejemplo de cómo los programas usan el entorno. Si se lo digo de forma explícitagnome-terminal
con el-e
correr cáscara específica - lo hará, pero no va a ser permanente. Por el contrario, el medio ambiente está mayormente inalterado (más sobre eso más adelante).Como puede ver, las variables de entorno y de posición son propiedades de un proceso / comando, no solo shell. Cuando se trata de scripts de shell, también siguen el modelo establecido por el lenguaje de programación C. Tomemos por ejemplo el C
main
función que normalmente se ve como, Donde
argc
es el número de argumentos de línea de comandos yargv
es efectivamente matriz de parámetros de línea de comandos, y luego estáenviron
la función (en Linux que deman -e 7 environ
) a las cosas de acceso como la ruta del directorio principal del usuario, lista de directorios enPATH
donde podemos buscar los ejecutables, etc. scripts de shell también se modelan de forma similar. En terminología de shell, tenemos parámetros posicionales$1
,$2
y así sucesivamente, mientras que$#
es el número de parámetros posicionales. ¿Qué hay de$0
? Ese es el nombre del ejecutable en sí, que también está modelado a partir del lenguaje de programación C:argv[0]
sería el nombre de su C "ejecutable". Y esto es bastante cierto para la mayoría de lenguajes de programación y script .conchas interactiva vs no interactivas
Una de las cosas que ya he insinuado es la distinción entre shells interactivos y no interactivos . El mensaje donde escribe los comandos: es interactivo, interactúa con el usuario. Por el contrario, cuando usted tiene un script de shell o ejecutar
bash -c''
eso es no interactivo.Y aquí es donde la distinción se vuelve importante. La cáscara que ya ejecuta un proceso, que se generó con los parámetros de posición (por
bash
shell de entrada es una "... cuyo primer carácter del argumento es un cero -., O uno iniciado con la opción --login" ( referencia ) )Por el contrario, las secuencias de comandos y proyectiles lanzados con
-c
opción puede aprovechar$1
y$2
argumentos. Por ejemplo,Tenga en cuenta que también lo he usado
sh
allí, porque una pequeña peculiaridad de la-c
opción es tomar el primer parámetro posicional y asignarlo, a$0
diferencia de ser un nombre del programa.Otra cosa que es importante tener en cuenta es que los parámetros posicionales son lo que yo llamo "framable". Observe cómo, primero lanzamos
bash
con sus propios parámetros posicionales, pero esos parámetros posicionales se convirtieron en parámetros paraecho
ystat
. Y cada programa lo entiende a su manera. Si le damos astat
una cadenaHello World
y no hay archivoHello World
, produciría un error;bash
lo trata simplemente como una cadena simple, perostat
espera que cadena a un nombre de archivo existente. Por el contrario, todos los programas estarían de acuerdo en que la variable de entornoHOME
es un directorio (a menos que el programador lo codifique de manera no razonable).¿Podemos jugar con las variables de entorno y los parámetros posicionales?
Técnicamente, podemos perder el tiempo con ambos, pero no debemos perder el tiempo con las variables de entorno, mientras que a menudo tenemos que proporcionar parámetros posicionales. Podemos ejecutar comandos de shell con anteponiendo una variable, por ejemplo:
También podemos colocar variables en el entorno simplemente usando
export variable=value
desde shell o script. O podemos ejecutar un comando con un entorno completamente vacío conenv -c command arg1 arg2
. Sin embargo, generalmente no se recomienda jugar con el entorno, especialmente usando variables en mayúsculas o sobrescribiendo variables de entorno ya existentes. Tenga en cuenta que se recomienda aunque no es una norma.Para los parámetros posicionales, la manera de ponerlos es obvio, sólo les anteponer al comando, sino que también hay formas de establecer ellos de otra forma , así como el cambio de la lista de los parámetros a través
shift
de comandos.En conclusión, el propósito de estos dos es diferente, y que existe por una razón. Espero personas obtuvieron una idea de esta respuesta, y fue muy divertido leyendo casi como lo fue para mí escribir esta respuesta.
Nota sobre el mandato set
El
set
comando, de acuerdo con el manual, se comporta así (del manual bash, énfasis agregado):En otras palabras
set
mira a variables específicas a Shell, algunos de los cuales resultan ser en el entorno, por ejemploHOME
. Por órdenes de contraste comoenv
yprintenv
vistazo a la variable de entorno real con la que se ejecuta un comando. Ver también esto .fuente
1="foo"
, pero más tarde descubrí que por POSIX definición de una "palabra" (que es un nombre de un objeto como variable o función) no puede comenzar con un dígito (véase una pregunta que he publicado sobre el tema ). Los parámetros posicionales aparentemente son una excepción a esta regla.$1
,$2
y así sucesivamente en el intérprete de comandos interactivo, y, de hecho, que se hace con elset
comando, a menudo para moverse por/bin/sh
la limitación de no tener matrices. Gracias por traer esto a mi atención. También voy a editar la respuesta en los próximos días, ya que se necesita un poco de esmalte extra y una actualización.conda
, cuando se ejecutasource conda/bin/activate
, comprueba si$1
,$2
, etc., se establecen, con el fin de determinar si se ejecuta como un script con argumentos o no. Esto termina rompiendo en sistemas que tienen los fijados en el entorno interactivo por alguna razón. Tengo la esperanza de averiguar si este comportamiento no estándar es una falla en el sistema de fijación de estas variables en el entorno interactivo, o en el programa para el uso de ellos para determinar si se ejecuta como un script.conda
los desarrolladores oa quienquiera que sea el autor original de dicha escritura, como la comprobación de${N}
los parámetros es definitivamente el camino equivocado. Hay preguntas sobre el mismo tema aquí y aquí , y de manera más o menos portátil es comprobar si${0}
es el mismo que el nombre del script, mientras quebash
en realidad tiene la variable de entorno para tal finLas
$1, $2, $3, ..., ${10}, ${11}
variables se denominan parámetros posicionales y se tratan en la sección del manual bash3.4.1
En cuanto a
$?
y$0
, estos parámetros especiales se tratan en la siguiente sección3.4.2
fuente
$1
,$2
... son los parámetros de posición , no son variables, dejar que las variables de entorno solo.En Bourne-como terminología cáscara,
$something
se llama parámetro de expansión (también cubre${something#pattern}
y más en algunas cáscaras como${array[x]}
,${param:offset}
,${x:|y}
y muchos operadores de más de expansión).Hay diferentes tipos de parámetros:
$foo
,$PATH
$1
,$2
... los argumentos que recibió su script)$0
,$-
,$#
,$*
,$@
,$$
,$!
,$?
...nombres de las variables en Bourne como conchas deben comenzar con un carácter alfabético (cualquier reconocida por la configuración regional o límite la a-zA-Z en función de la cáscara) y el guión bajo y seguido de cero o más caracteres alfanuméricos o guiones.
Dependiendo de la cáscara, las variables pueden tener diferentes tipos (escalar, matriz, hash) o ciertos atributos dados (de sólo lectura, exportados caso, inferior ...).
Algunas de estas variables son creados por el shell o tienen un significado especial para el shell (como
$OPTIND
,$IFS
,$_
...)Las variables de shell que tienen el atributo de exportación se exportan automáticamente como variables de entorno a los comandos que ejecuta el shell.
variable de entorno es un concepto separado de variables de shell. Exportar una variable de shell no es la única forma de pasar una variable de entorno a la ejecución de un comando.
pasará una
VAR
variable de entorno para elprintenv
comando (que le estamos diciendo a imprimir su contenido), pero también se puede hacer:o:
por ejemplo.
Las variables de entorno pueden tener cualquier nombre (pueden contener cualquier carácter, sino
=
e incluso puede estar vacía). No es una buena idea para dar un nombre que no es compatible con el de un nombre de variable Bourne-como la cáscara de una variable de entorno, pero es posible:Conchas trazarán las variables de entorno que se reciben para bombardear las variables sólo para aquellas variables de entorno cuyos nombres son válidos variables de shell (y en algunos proyectiles ignoran algunos especiales como
$IFS
).Entonces, si bien podría pasar una
1
variable de entorno a un comando:Eso no significa que llamar a un shell con esa variable de entorno establecería el valor del
$1
parámetro:fuente
No, estos son parámetros del script. Por ejemplo, si llamas a tu script como:
a continuación, dentro de la secuencia de comandos, habrá estos parámetros disponibles como
y los $ 0 es el nombre del script mismo.
Así que cuando estás fuera del guión, estas variables no están disponibles (excepto $ 0, lo que muestra / bin / bash - el depósito propiamente dicho).
fuente
$0
apunten a su proceso de terminal (bash probable) actual y$?
es simplemente el código de salida del último proceso.gnome-terminal
con argumentos (gnome-terminal Hello World
). Pude ver$0
, pero no pude ver$1
y$2
.