Distribuir una secuencia de commands: ¿Debo usar / bin / gawk o / usr / bin / gawk para shebang?

¿Está gawk in / bin o / usr / bin por lo general? Me gustaría ir con #!/usr/bin/env gawk pero luego no puedo usar arguments. En este momento estoy usando #!/bin/gawk -f . El script es muy largo y contiene muchas comillas simples y funciona con stdin.

El manual de GNU Awk tiene la sección 1.1.4 Progtwigs ejecutables awk donde usa #! / Bin / awk en su ejemplo, pero continúa para decir:

Tenga en count que en muchos sistemas awk se puede encontrar en /usr/bin lugar de en /bin . Caveat Emptor.

¿Qué hace la mayoría de la gente? He leído que sed está supuestamente estandarizado en / bin, mientras que Perl supuestamente está estandarizado en / usr / bin (la misma página que el enlace sed, pero no me permiten hacer un tercer enlace para esta publicación). ¿Qué hay de awk / gawk? ¿Alguien sabe cuál es más común o popular?

Shebang no tenía la intención de ser tan flexible . Puede haber algunos casos donde funciona un segundo parámetro , creo que FreeBSD es uno de ellos.

Gawk y la mayoría de las utilidades que vienen con el sistema operativo se espera que estén en /usr/bin/ .

En los días anteriores de UNIX, era común tener /usr/ montado sobre NFS o algunos medios less costosos para ahorrar espacio en el disco local y costo por estación de trabajo. /bin/ se suponía que tenía todo lo necesario para arrancar en modo de usuario único . Como /usr/ no se montó en un medio confiable, /bin/ incluyó suficientes utilidades para que sea lo suficientemente amigable para la administración general y la solución de problemas.

Esto fue henetworkingado en Linux inicialmente, pero como el espacio del disco ya no es un problema y en la mayoría de los casos /usr/ está en el sistema de files raíz, la tendencia actual es mover todo en /usr/bin (al less en el mundo de Linux). Por lo tanto, se espera que la mayoría de los services instalados por una distribución se encuentren allí. Incluso las utilidades más básicas, como cp , rm , ls , etc. (bueno, todavía no).

En cuanto a la elección shebang. Tradicionalmente, esto es algo que los administradores o usuarios tienen que editar de acuerdo con su entorno. Para todo lo que un desarrollador sabe, en los sistemas de otras personas, el intérprete podría estar en cualquier parte del sistema de files (por ejemplo, /usr/local/bin , /opt/gawk-4.0.1/bin ). Los scripts correctamente empaquetados (rpm, deb, etc.) vienen con una dependencia de un package de distribución (es decir, el intérprete tiene una location conocida) o un script de configuration que configura el hashbang adecuado durante la installation.

Si no necesita pasar arguments al command, entonces #!/usr/bin/env gawk es el path a seguir, sin embargo muchos kernels (incluyendo Linux) solo aceptan un único argumento para shebang programs.

De lo contrario, puede crear un progtwig políglota que sea a la vez un contenedor de shell y el script de awk. Aquí hay uno para awk.

 #!/bin/sh true + /; exec gawk -f "$0"; exit; / {} # awk script starts here 

Análisis de Shell:

  • true + /; – el command true (que no hace nada) con dos arguments inertes + y / .
  • La llamada a gawk . Puede ser cualquier fragment de shell que no contenga líneas nuevas y donde se escriben barras \/ (al shell no le importa, excepto las comillas internas).
    La llamada usa a exec para replace el shell con gawk en lugar de ejecutar gawk como un subprocess.
  • exit; – salir del shell, en caso de que gawk no se haya encontrado. Cualquier cosa posterior se ignora, excepto que debe ser una syntax válida del shell en caso de que el shell intente analizar toda la línea antes de comenzar a ejecutarla.

Análisis de Awk:

  • El bit entre barras es una expresión regular.
  • true + /REGEX/ – una condición. true es una variable indefinida, por lo que su valor numérico es 0, no es que importe.
  • {} – Si dicha condición se cumple, no haga nada.

La solución propuesta por Gilles es realmente un muy buen enfoque (finalmente, tengo la reputación de votar en su publicación :)).

En cualquier caso, hasta donde yo entiendo el command exec , hace que la exit inmediatamente después de que sea innecesaria, de hecho inalcanzable, ya que awk reemplaza el process de shell.

Además, para permitir que el script awk acceda a sus parameters de invocación, sugeriría algunos cambios en la solución propuesta:

 #!/bin/sh true + /; exec -a "$0" gawk -f "$0" -- "$@"; / {} # awk script starts here 

El -a "$0" permite que el script tenga acceso a su nombre de invocación, de lo contrario siempre obtendrá un awk o gawk al acceder a la ARGV[0] . Del mismo modo, el "$@" permite que el guión acceda a los parameters restantes en el ARGV[1...N] y el -- antes de permitir que el guión reciba -<something> arguments -<something> sin que gawk los interprete están destinados para él .

Una cosa para recordar / considerar es agregar una exit(0); statement al final del bloque BEGIN { ... } del progtwig de script awk ; de lo contrario, awk amenazará con pasar todos los parameters al script como files de input. (Tenga en count que no tiene nada que ver, en absoluto, con la statement de exit que eliminamos de la línea true + ... , esta era una statement de shell inalcanzable, mientras que esta salida sugerida está en el código awk).