Comment faire pour utiliser plusieurs arguments pour awk avec un shebang (c #!)?
J'aimerais exécuter une gawk script avec --re-interval
à l'aide d'une arborescence. Le "naïf" approche de
#!/usr/bin/gawk --re-interval -f
... awk script goes here
ne fonctionne pas, puisque gawk est appelée avec le premier argument "--re-interval -f"
(pas répartis autour de l'espace), dont il ne comprend pas. Est-il une solution pour que?
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 à s'émerveiller et de mettre le script dans un autre fichier, mais je me demandais si il y avait moyen de faire cela dans un seul fichier.
Le comportement de shebang lignes diffère d'un système à l'autre - au moins dans Cygwin il ne se fend pas les arguments par des espaces. Je viens de soins sur la façon de le faire sur un système qui se comporte comme ça; le script n'est pas destiné à être portables.
- Un idiot d'expérimenter ce que j'ai fait était avec un script à l'aide d'un autre script sur la ligne shebang, qui a divisé les arguments correctement.
- cela soulève une autre question, que le comportement de shebang lignes diffère également d'un système à l'wrt si le programme appelé lui-même peut être un script.
- stackoverflow.com/questions/17458528/why-does-this-snippet-work
- Avec les versions récentes de gawk (>= 4.0),
--re-interval
n'est plus nécessaire (voir [gnu.org/software/gawk/manual/...).
Vous devez vous connecter pour publier un commentaire.
Cela semble fonctionner pour moi avec (g)awk.
Note le
#!
s'exécute/bin/sh
, de sorte que ce script est d'abord interprétée comme un script shell.Au premier abord, j'ai simplement essayé
"exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"
, mais awk traitée comme une commande et imprimés chaque ligne de saisie sans condition. C'est pourquoi j'ai mis dans learbitrary_long_name==0
- c'est censé faire échouer tout le temps. Vous pourriez le remplacer par n'importe quoi de la chaîne. En fait, je cherchais un faux-condition dans awk qui ne les empêcherait pas de script shell.Dans le script shell, le
arbitrary_long_name==0
définit une variable appeléearbitrary_long_name
et la met à égalité à=0
.bash
, ou qu'il sera de travailler avec tout POSIXsh
? Et je n'utilise pasawk
souvent, donc je ne suis pas sûr que mon truc sur la deuxième ligne est un bon moyen de forcerawk
d'ignorer la ligne.arbitrary_long_name
ne rentrera pas en conflit avec une variable utilisée dans le réel awk programme, je ne vois aucun problème. Est-il quelque chose que je suis absent?La ligne shebang n'a jamais été spécifiée dans POSIX, SUS, LSB ou toute autre spécification. Autant que je sache, il n'a même pas été correctement documentée.
Il s'agit d'un rough consensus sur ce qu'il fait: prendre tout ce qui est entre les
!
et la\n
etexec
il. L'hypothèse est que tout entre les!
et la\n
est une intégrale de chemin d'accès absolu à l'interprète. Il n'y a pas de consensus sur ce qui se passe s'il contient des espaces.Heureusement, 1. et 4. semblent avoir disparu, mais 3. est assez répandue, de sorte que vous ne peut tout simplement pas compter sur d'être en mesure de passer plus d'un argument.
Et depuis le lieu de commandes est pas spécifiée dans POSIX ou SUS, vous utilisez généralement que seul argument en passant de l'exécutable nom à
env
de sorte que il pouvez déterminer l'emplacement de l'exécutable; par exemple:[Évidemment, ce encore suppose un chemin particulier pour
env
, mais il n'existe que très peu de systèmes où il vit dans/bin
, c'est généralement sans danger. L'emplacement deenv
est beaucoup plus standardisée que l'emplacement degawk
, ou pire encore, quelque chose commepython
ouruby
ouspidermonkey
.]Ce qui signifie que vous ne pouvez pas utiliser effectivement tout arguments à tous les.
-S
interrupteur qui aide ici, mais il n'est pas présent sur mon Linuxenv
, et je soupçonne n'est pas disponible sur gygwin, soit. @hstoerr, d'autres utilisateurs avec des situations différentes peuvent être la lecture de vos questions plus tard, donc, en général, portable réponses sont préférables, même si vous n'avez pas maintenant nécessitent de la portabilité.#!/bin/sh
et/usr/bin/env gawk --re-interval -f my-script.awk
. Est-ce exact?-S
option serait utile d'avoir ajouté à la GNU coreutils version deenv
?? Et/ou le noyau linux shebang comportement modifié pour être comme dans l'option 2... mais je suppose qu'il y aurait des problèmes de compatibilité avec le dernier changement.#!
lui-même n'est pas portable. Par exemple, Windows ne reconnaît pas la présente convention "nativement" à tous. Un argument a bang est nécessaire sur Unix traditionnellement pour être en mesure de faire#!/usr/bin/awk -f
.#!/usr/bin/env ruby
ou les goûts.#!/bin/bash -ex
, il est équivalent à l'exécution de/bin/bash -ex /path/too/foo arg1 arg2
. Cette fonctionnalité est gérée par le noyau.Je suis tombé sur le même problème, sans solution apparente en raison de la façon dont les espaces sont traités dans un shebang (au moins sous Linux).
Toutefois, vous pouvez passer plusieurs options dans un shebang, tant qu'ils sont options courtes et ils peuvent être concaténées (GNU façon).
Par exemple, vous ne pouvez pas avoir
mais vous pouvez avoir
Évidemment, cela ne fonctionne que lorsque les options ont une courte équivalents et ne pas prendre des arguments.
Sous Cygwin et Linux tout ce qui suit le chemin de l'arborescence n'obtient analysé le programme comme un argument.
Il est possible de pirater contourner ce problème en utilisant un autre
awk
script à l'intérieur de l'arborescence:Execute
{system("/usr/bin/gawk --re-interval -f " FILENAME); exit}
en awk.Et ce sera d'exécuter
/usr/bin/gawk --re-interval -f path/to/your/script.awk
dans vos systèmes shell.Bien que n'étant pas exactement portable, en commençant par coreutils 8h30 et selon sa documentation vous serez en mesure d'utiliser:
Donc donné:
vous obtiendrez:
et dans le cas où vous êtes curieux de
showargs
est:Réponse originale à cette question ici.
Le dessus de la coquille shebang truc, c'est plus portable que
/usr/bin/env
.python
, mais cette question est à proposawk
.Dans le gawk manuel (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 rester bouche bée à partir d'une ligne shebang. Il est dit que l'OS va traiter tout ce qui est après le chemin d'accès à gawk comme un seul argument. Peut-être il ya une autre façon de spécifier la
--re-interval
option? Peut-être que votre script peut faire référence à votre shell dans la ligne shebang, exécutezgawk
comme une commande, et d'inclure le texte de votre script comme "here document".gawk
, mais vous pourriez encore être en mesure de tuyau de quelque chose en plus de la sortie stderr (qui est, de rediriger stdout vers stderr avant de tuyauterie dans ce script). Je ne l'ai jamais essayé, mais aussi longtemps que le premier processus n'a pas d'émettre quoi que ce soit sur stderr, il pourrait fonctionner. Vous pouvez également créer un tube nommé (linuxjournal.com/content/using-named-pipes-fifos-bash) si vous voulez vous assurer que rien d'autre ne l'utilise.Pourquoi ne pas utiliser
bash
etgawk
lui-même, de passer au-delà de cette arborescence, lu le script et de le passer comme un fichier à une deuxième instance degawk [--with-whatever-number-of-params-you-need]
?(la même chose peut naturellement aussi être accompli avec, par exemple,
sed
outail
, mais je pense qu'il y a une sorte de beauté en fonction debash
etgawk
lui-même;)Juste pour le fun: il est le suivant assez bizarre solution qui redirige stdin et le programme à l'aide des descripteurs de fichiers 3 et 4. Vous pouvez également créer un fichier temporaire pour le script.
Une chose est ennuyeux à ce sujet: le shell extension variable sur le script, de sorte que vous avez à citer chaque $ (comme le fait dans la deuxième ligne du script) et probablement plus.
Pour une solution portable, utiliser
awk
plutôt quegawk
, appelez le standard de la BOURNE shell (/bin/sh
) avec votre beau spectacle, et d'invoquerawk
directement, en passant le programme sur la ligne de commande comme ici le document plutôt que via stdin:Remarque: pas
-f
argumentawk
. Qui laissestdin
disponibles pourawk
pour lire l'entrée de. En supposant que vous avezgawk
installé et sur votrePATH
, qui réalise tout ce que je pense, ils ont essayé de faire avec l'original de votre exemple (en supposant que vous vouliez le contenu du fichier pour être le script awk et pas l'entrée, je pense que votre shebang approche aurait traité comme).