«set -o noglob» en bash shell script

Por lo general se escribe SQL declaraciones en línea en un shell de Bash script para ser ejecutado en SQLPlus como-

#! /bin/sh

sqlplus user/[email protected]<<EOF
insert into dummy1 
select * from dummy2;

commit;
exit;
EOF

Que esto iba a funcionar muy bien y va a insertar filas en dummy1 cuando se ejecuta. Un colega mío me vino el otro día con un script como el siguiente (simplificado)

#! /bin/sh    
sqlvar="insert into dummy1 select * from dummy2;commit;"    
echo $sqlvar|sqlplus user/[email protected]

El problema con esto es que cuando se ejecuta la variable sqlvar expande el * ser la de todos los archivos en el directorio actual y, finalmente, el error como

SQL> insert into dummy1 select <--all the file names in the current directory--> 
from dummy2;commit
                                                    *
ERROR at line 1:
ORA-00923: FROM keyword not found where expected

Nuestra primera estancia en este caso fue la shell fue la interpretación de * en un comodín contexto y el listado de todos los nombres de archivo, mientras que la variable de shell de expansión (no muy seguro de por qué….???). Así que, para entender esto, hicimos algo como la siguiente-

$ var="hello *"
$ echo $var
hello <--all the file names in the current directory-->

Pero

$*
ksh: somefile.sh: 0403-006 Execute permission denied. #since it had no execute permission

Hay un número de otros archivos en el directorio y no estoy seguro de por qué * eligió para ejecutar somefile.sh o apunta a somefile.sh.

Después, un poco de excavación nos dimos cuenta de que, utilizando set -o noglob iba a resolver este problema por completo, como

#! /bin/sh
set -o noglob
sqlvar="insert into dummy1 select * from dummy2;\n commit;"    
echo $sqlvar|sqlplus user/[email protected]

Hay algún conflicto o, más bien contradictorias descripción de setting noglob, a través de internet. Así que estoy buscando si alguien podría explicar las curiosidades de este bit.

InformationsquelleAutor Annjawn | 2012-09-01

2 Kommentare

  1. 9

    Después, un poco de excavación nos dimos cuenta de que, por medio de set-o noglob iba a resolver este problema por completo

    No resuelve el problema tanto como oculta. El tema en cuestión es la falta de cotización. Citando las variables generalmente es una buena práctica, ya que impide la concha de hacer cosas inesperadas cuando la variable contiene caracteres especiales, espacios en blanco, etc.

    Desactivación de englobamiento de evitar que el * de ser ampliado, pero que generalmente no es algo que usted quiere hacer. Va a dejar de usar * y ?, pero las cosas pueden romperse si se utilizan otros caracteres especiales.

    Hay un número de otros archivos en el directorio y no estoy seguro de qué eligió a ejecutar somefile.sh o es señalado somefile.sh.

    Aquí * se expande a todos los nombres de archivo en el directorio actual y, a continuación, esta lista de archivos se convierte en la línea de comandos. El shell termina tratando de ejecutar cualquiera que sea el nombre del archivo es la primera por orden alfabético.


    Así, la forma correcta de solucionar este es citar la variable:

    echo "$sqlvar" | sqlplus user/[email protected]

    Que va a resolver el comodín problema. El otro problema es que necesita el \n secuencia de escape que se interpreta como una nueva línea. El shell no hacer esto de forma automática. Para obtener \n a trabajar utilizar echo -e:

    echo -e "$sqlvar" | sqlplus user/[email protected]

    O uso de la cadena de sintaxis literal $'...'. Esa es la única cita con un signo de dólar en el frente.

    sqlvar=$'insert into dummy1 select * from dummy2;\n commit;'
    echo "$sqlvar" | sqlplus user/[email protected]

    (O eliminar el salto de línea.)

    • gracias, pero estábamos buscando el significado de la configuración de noglob (que al parecer también se resuelve el problema). La nueva línea char wan no hay de eso es mi error se corrigió en la pregunta.
  2. 5

    Antes de comenzar: @Juan Kugelman la respuesta (es) adecuada (citando) es la manera correcta de resolver este problema. Configuración de noglob sólo resuelve algunas variantes del problema, y crea otros problemas potenciales en el proceso.

    Pero ya que usted pidió lo set -o noglob hace, aquí están los extractos pertinentes de la ksh hombre de la página (por CIERTO, sus etiquetas decir bash, pero el mensaje de error que dice ksh. Supongo que usted está utilizando ksh).

    noglob  Same as -f.

    -f      Disables file name generation.

    File Name Generation.
       Following splitting, each field is scanned for the characters *, ?,  (,
       and  [  unless  the -f option has been set.  If one of these characters
       appears, then the word is regarded as a pattern.  Each file name compo-
       nent  that  contains  any  pattern character is replaced with a lexico-
       graphically sorted set of names that  matches  the  pattern  from  that
       directory.

    Entonces, ¿qué significa eso? Aquí está un ejemplo rápido que debería mostrar el efecto:

    $ echo *
    file1 file2 file3 file4
    $ ls *
    file1 file2 file3 file4
    $ *    # Note that this is equivalent to typing "file1 file2 file3 file4" as a command -- file1 is treated as the command (which doesn't exist), the rest as arguments to it
    ksh: file1: not found

    Ahora ver qué cambios con noglob conjunto:

    $ set -o noglob
    $ echo *
    *
    $ ls *
    ls: *: No such file or directory
    $ *
    ksh: *: not found

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea