Comment utiliser plusieurs arguments pour awk avec un shebang (i.e. #!)?

j'aimerais exécuter un script gawk avec --re-interval en utilisant un shebang. L'approche "naïve" de

#!/usr/bin/gawk --re-interval -f
... awk script goes here

ne fonctionne pas, puisque gawk est appelé avec le premier argument "--re-interval -f" (non divisé autour de l'espace blanc), qu'il ne comprend pas. Est-il une solution pour cela?

bien sûr, vous pouvez soit pas appel gawk directement, mais l'envelopper dans un script shell qui divise le premier argument, ou faire un script shell qui appelle ensuite gawk et mettre le script dans un autre fichier, mais je me demandais s'il y avait un moyen de le faire dans un fichier.

le comportement des lignes de shebang diffère d'un système à l'autre - au moins dans Cygwin il ne divise pas les arguments par des espaces blancs. Je me soucie juste de savoir comment le faire sur un système qui se comporte comme cela; le script n'est pas censé être portable.

100
demandé sur sanmai 2010-11-29 14:04:21

9 réponses

Cela semble fonctionner pour moi avec (g)awk.

#!/bin/sh
arbitrary_long_name==0 "exec" "/usr/bin/gawk" "--re-interval" "-f" ""151900920"" "$@"


# The real awk program starts here
{ print "151900920" }

notez que #! exécute /bin/sh , donc ce script est d'abord interprété comme un script shell.

au début, j'ai simplement essayé "exec" "/usr/bin/gawk" "--re-interval" "-f" ""151930920"" "$@" , mais awk a traité cela comme une commande et a imprimé chaque ligne d'entrée inconditionnellement. C'est pourquoi j'ai mis le arbitrary_long_name==0 - il est censé échouer tout le temps. Vous pourriez le remplacer par du charabia. En gros, j'étais à la recherche pour une fausse condition dans awk qui n'affecterait pas négativement le script shell.

dans le script shell, le arbitrary_long_name==0 définit une variable appelée arbitrary_long_name et la définit comme =0 .

19
répondu Aaron McDaid 2014-09-26 09:48:27

la ligne de shebang n'a jamais été spécifiée dans POSIX, SUS, LSB ou toute autre spécification. AFAIK, il n'a même pas été correctement documenté.

il y a un consensus grossier sur ce qu'il fait: prenez tout entre le ! et le \n et exec il. L'hypothèse est que tout entre le ! et le \n est un chemin absolu vers l'interprète. Il n'y a pas de consensus sur ce qui se passe si contient des espaces.

  1. certains systèmes d'exploitation traitent simplement la chose entière comme le chemin. Après tout, dans la plupart des systèmes d'exploitation, les espaces ou les tirets sont légaux dans un chemin.
  2. certains systèmes d'exploitation se séparent à whitespace et traitent la première partie comme le chemin vers l'interpréteur et le reste comme des arguments individuels.
  3. certains systèmes d'exploitation scindé à la premier espaces et de traiter les la partie avant comme le chemin vers l'interpètre et le reste comme un simple argument (qui est ce que vous voyez).
  4. certains ne supportent même pas les lignes de shebang du tout .

Heureusement, 1. et 4. semblent avoir disparu, mais 3. est assez répandue, de sorte que vous ne pouvez tout simplement pas compter sur la possibilité de passer plus d'un argument.

et comme l'emplacement des commandes est également non spécifié dans POSIX ou SUS, vous utilisez généralement ce seul argument en passant le "nom" de l'exécutable à env de sorte que it puisse déterminer l'emplacement de l'exécutable; par exemple:

#!/usr/bin/env gawk

[évidemment, ce encore assume un chemin particulier pour env , mais il n'y a que très peu de systèmes où il vit dans /bin , ce qui est généralement sûr. L'emplacement de env est beaucoup plus standardisé que l'emplacement de gawk ou même pire quelque chose comme python ou ruby ou spidermonkey .]

ce qui signifie que vous ne pouvez pas réellement utiliser tout arguments du tout .

144
répondu Jörg W Mittag 2014-06-17 21:18:16

je suis tombé sur la même question, sans solution apparente en raison de la façon dont les espaces blancs sont traités dans un shebang (au moins sur Linux).

cependant, vous pouvez passer plusieurs options dans un shebang, à condition qu'elles soient courtes options et qu'elles puissent être concaténées (la manière GNU).

par exemple, vous ne pouvez pas avoir

#!/usr/bin/foo -i -f

mais vous pouvez avoir

#!/usr/bin/foo -if

évidemment, cela ne fonctionne que lorsque les options ont des équivalents courts et ne prennent pas d'arguments.

11
répondu ℝaphink 2011-02-10 11:53:43

sous Cygwin et Linux tout ce qui suit le chemin du shebang est analysé au programme comme un seul argument.

il est possible de contourner cela en utilisant un autre script awk à l'intérieur du shebang:

#!/usr/bin/gawk {system("/usr/bin/gawk --re-interval -f " FILENAME); exit}

ceci exécutera {system("/usr/bin/gawk --re-interval -f " FILENAME); exit} dans awk.

Et ceci exécutera /usr/bin/gawk --re-interval -f path/to/your/script.awk dans votre shell système.

11
répondu Moritz 2016-12-17 14:35:13
#!/bin/sh
''':'
exec YourProg -some_options ""151900920"" "$@"
'''

le shebang de coquille ci-dessus est plus portable que /usr/bin/env .

5
répondu user3123730 2018-02-07 15:14:55

In the gawk manual (http://www.gnu.org/manual/gawk/gawk.html), la fin de la section 1.14 notez que vous ne devez utiliser qu'un seul argument lors de l'exécution de gawk à partir d'une ligne shebang. Il est dit que L'OS traitera tout après le chemin de gawk comme un argument unique. Peut-être y a-t-il une autre façon de spécifier l'option --re-interval ? Peut-être que votre script peut faire référence à votre shell dans la ligne de shebang, lancer gawk comme une commande, et inclure le texte de votre script comme un " ici document."

3
répondu bta 2010-11-29 13:10:24

pourquoi ne pas utiliser bash et gawk lui-même, pour passer devant shebang, lire le script, et le passer comme un fichier à une deuxième instance de gawk [--with-whatever-number-of-params-you-need] ?

#!/bin/bash
gawk --re-interval -f <(gawk 'NR>3' "151900920" )
exit
{
  print "Program body goes here"
  print 
}

(- la même chose pourrait naturellement aussi être accomplie avec par exemple sed ou tail , mais je pense qu'il y a une sorte de beauté qui dépend seulement de bash et gawk lui-même;)

2
répondu conny 2017-09-13 09:55:40

juste pour le plaisir: il y a la solution suivante assez étrange qui redirige stdin et le programme à travers les descripteurs de fichier 3 et 4. Vous pouvez également créer un fichier temporaire pour le script.

#!/bin/bash
exec 3>&0
exec <<-EOF 4>&0
BEGIN {print "HALLO"}
{print $1}
EOF
gawk --re-interval -f <(cat 0>&4) 0>&3

une chose est ennuyeuse à ce sujet: le shell fait l'expansion variable sur le script, donc vous devez citer chaque $ (Comme fait dans la deuxième ligne du script) et probablement plus que cela.

0
répondu Hans-Peter Störr 2013-03-15 13:50:24

pour une solution portable, utilisez awk plutôt que gawk , invoquez le shell BOURNE standard ( /bin/sh ) avec votre shebang, et invoquez awk directement, en passant le programme sur la ligne de commande comme un document ici plutôt que via stdin:

#!/bin/sh
gawk --re-interval <<<EOF
PROGRAM HERE
EOF

Note: no -f argument à awk . Cela laisse stdin disponible pour awk à lire en entrée. En supposant que vous avez gawk installé et sur votre PATH , cela réalise tout ce que je pense que vous essayiez de faire avec votre exemple original (en supposant que vous vouliez que le contenu du fichier soit le script awk et non l'entrée, ce que je pense que votre approche shebang l'aurait traité comme).

-1
répondu lharper71 2013-03-13 21:06:19