Me gustaría ejecutar un script de gawk--re-interval
usando un shebang. El enfoque "ingenuo" de
#!/usr/bin/gawk --re-interval -f
... awk script goes here
no funciona, ya que se llama a gawk con el primer argumento "--re-interval -f"
(no dividido entre los espacios en blanco), que no comprende. ¿Hay alguna solución para eso?
Por supuesto, no puede llamar a gawk directamente, sino envolverlo en un script de shell que divide el primer argumento, o crear un script de shell que luego llame a gawk y coloque el script en otro archivo, pero me preguntaba si había alguna forma de hacerlo. esto dentro de un archivo.
El comportamiento de las líneas shebang difiere de un sistema a otro, al menos en Cygwin no divide los argumentos por espacios en blanco. Solo me importa cómo hacerlo en un sistema que se comporta así; el script no está destinado a ser portátil.
--re-interval
ya no es necesario (ver [ gnu.org/software/gawk/manual/… ).Respuestas:
Esto parece funcionar para mí con (g) awk.
Tenga en cuenta las
#!
carreras/bin/sh
, por lo que este script se interpreta primero como un script de shell.Al principio, simplemente lo intenté
"exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"
, pero awk lo trató como un comando e imprimió cada línea de entrada incondicionalmente. Por eso puse elarbitrary_long_name==0
- se supone que falla todo el tiempo. Podrías reemplazarlo con una cadena de galimatías. Básicamente, estaba buscando una condición falsa en awk que no afectaría negativamente al script de shell.En el script de shell,
arbitrary_long_name==0
define una variable llamadaarbitrary_long_name
y la iguala a=0
.fuente
bash
, o funcionará con cualquier POSIXsh
? Y no lo uso aawk
menudo, así que no estoy seguro de que mi truco en la segunda línea sea una buena forma de forzarawk
a ignorar la línea.arbitrary_long_name
no entre en conflicto con una variable utilizada en el programa awk real, no veo ningún problema. ¿Se me escapa algo?#!/bin/sh -
lugar de#!/bin/sh
para proteger el script de posibles comportamientos incorrectos de una manera peligrosa si se invoca con un argumento cero que tiene-
como primer carácter. Esto puede suceder accidentalmente en lenguajes de programación como C, donde es fácil equivocarse accidentalmente al olvidarse de pasar el nombre del programa invocado como parte de la matriz de argumentosexecve
y funciones similares, y si las personas olvidan habitualmente protegerse contra él, también puede ocurrir. terminan siendo el último paso en una vulnerabilidad explotable maliciosamente que permite a un atacante obtener un shell interactivo.La línea shebang nunca se ha especificado como parte de POSIX, SUS, LSB o cualquier otra especificación. AFAIK, ni siquiera se ha documentado adecuadamente.
Existe un consenso aproximado sobre lo que hace: tomar todo entre el
!
y el\n
y elexec
. Se asume que todo lo que se encuentra entre el!
y el\n
es una ruta absoluta y completa al intérprete. No hay consenso sobre lo que sucede si contiene espacios en blanco.Afortunadamente, 1. y 4. parecen haberse extinguido, pero 3. está bastante extendido, por lo que simplemente no puede confiar en poder pasar más de un argumento.
Y puesto que la ubicación de los comandos también no se especifica en POSIX o SUS, se utiliza generalmente hasta que solo argumento mediante el paso del ejecutable de nombre a
env
fin de que se pueda determinar la ubicación del ejecutable; p.ej:[Obviamente, esto todavía asume una ruta particular para
env
, pero solo hay muy pocos sistemas donde vive/bin
, por lo que generalmente es seguro. La ubicación deenv
es mucho más estandarizada que la ubicación de,gawk
o incluso peor, algo comopython
oruby
ospidermonkey
.]Lo que significa que en realidad no puede utilizar ningún argumento en absoluto .
fuente
-S
interruptor que ayuda aquí, pero no está presente en mi Linuxenv
, y sospecho que tampoco está disponible en gygwin. @hstoerr, es posible que otros usuarios con diferentes situaciones lean sus preguntas más tarde, por lo que, en general, son preferibles las respuestas portátiles, incluso si ahora no necesita la portabilidad.#!/bin/sh
y/usr/bin/env gawk --re-interval -f my-script.awk
. ¿Es eso correcto?#!
sí mismo no es portátil. Por ejemplo, Windows no reconoce esta convención "nativamente" en absoluto. Tradicionalmente, se necesita un argumento único en Unix para poder hacerlo#!/usr/bin/awk -f
.#!/usr/bin/env ruby
o los me gusta.Aunque no es exactamente portátil, a partir de coreutils 8.30 y según su documentación podrás utilizar:
Así dado:
conseguirás:
y por si tienes curiosidad
showargs
es:Respuesta original aquí .
fuente
Me encontré con el mismo problema, sin una solución aparente debido a la forma en que se tratan los espacios en blanco en un shebang (al menos en Linux).
Sin embargo, puede pasar varias opciones en un shebang, siempre que sean opciones cortas y se puedan concatenar (al modo GNU).
Por ejemplo, no puedes tener
pero puedes tener
Obviamente, eso solo funciona cuando las opciones tienen equivalentes cortos y no aceptan argumentos.
fuente
En Cygwin y Linux, todo lo que sigue a la ruta del shebang se analiza en el programa como un argumento.
Es posible solucionar esto usando otro
awk
script dentro del shebang:Esto se ejecutará
{system("/usr/bin/gawk --re-interval -f " FILENAME); exit}
en awk.Y esto se ejecutará
/usr/bin/gawk --re-interval -f path/to/your/script.awk
en el shell de su sistema.fuente
El truco de shebang de shell anterior es más portátil que
/usr/bin/env
.fuente
python
, pero esta pregunta es sobreawk
.En el manual de gawk (http://www.gnu.org/manual/gawk/gawk.html), al final de la sección 1.14, tenga en cuenta que solo debe usar un único argumento cuando ejecute gawk desde una línea shebang. Dice que el sistema operativo tratará todo después de la ruta para mirar boquiabierto como un solo argumento. ¿Quizás haya otra forma de especificar la
--re-interval
opción? Quizás su script pueda hacer referencia a su shell en la línea shebang, ejecutarsegawk
como un comando e incluir el texto de su script como un "documento aquí".fuente
gawk
, pero es posible que aún pueda canalizar algo a través de stderr (es decir, redirigir stdout a stderr antes de canalizar a este script). En realidad, nunca lo he intentado, pero siempre que el primer proceso no emita nada en stderr, podría funcionar. También puede crear una tubería con nombre ( linuxjournal.com/content/using-named-pipes-fifos-bash ) si desea asegurarse de que nada más la esté usando.¿Por qué no usar
bash
ygawk
sí mismo, para omitir shebang, leer el script y pasarlo como un archivo a una segunda instancia degawk [--with-whatever-number-of-params-you-need]
?(-lo mismo, naturalmente, también podría lograrse con eg
sed
otail
, pero creo que hay algún tipo de belleza que depende solo debash
y degawk
sí mismo;)fuente
Simplemente cómico: existe la siguiente solución bastante extraña que redirige stdin y el programa a través de los descriptores de archivo 3 y 4. También puede crear un archivo temporal para el script.
Una cosa es molesta acerca de esto: el shell realiza una expansión de variables en el script, por lo que debe citar cada $ (como se hace en la segunda línea del script) y probablemente más que eso.
fuente
Para una solución portátil, use en
awk
lugar degawk
, invoque el shell BOURNE estándar (/bin/sh
) con su shebang, e invoqueawk
directamente, pasando el programa en la línea de comando como un documento aquí en lugar de a través de stdin:Nota: no hay
-f
argumento paraawk
. Eso dejastdin
disponible paraawk
leer la entrada. Asumiendo que tienesgawk
instalado y en suPATH
, eso logra todo lo que creo que estaba tratando de hacer con su ejemplo original (suponiendo que quisiera que el contenido del archivo fuera el script awk y no la entrada, que creo que su enfoque shebang lo habría tratado como ).fuente