Comment écrire un script qui accepte les entrées d'un argument de nom de fichier ou de stdin?
par exemple, vous pouvez utiliser less
cette méthode. on peut exécuter less filename
et de manière équivalente cat filename | less
.
y a-t-il un moyen facile de le faire "hors de la boîte"? ou dois-je réinventer la roue et écrire un peu de logique dans le script?
command-line
bash
stdin
Gil Hoch
la source
la source
Réponses:
Si l'argument de fichier est le premier argument de votre script, vérifiez qu'il existe un argument (
$1
) et qu'il s'agit d'un fichier. Sinon lire les entrées de stdin -Donc, votre script pourrait contenir quelque chose comme ceci:
par exemple, vous pouvez appeler le script comme
ou
Edit Quelques explications du script:
[ $# -ge 1 -a -f "$1" ]
- Si au moins un argument de ligne de commande ($# -ge 1
) AND (opérateur -a) le premier argument est un fichier (-f teste si "$ 1" est un fichier), le résultat du test est vrai.&&
est l'opérateur logique AND du shell. Si test est vrai, attribuezinput="$1"
etcat $input
le fichier sera généré.||
est l'opérateur OU logique du shell. Si le test est faux, les commandes suivantes||
sont analysées. l'entrée est assignée à "-". La commandecat -
lit depuis le clavier.En résumé, si l'argument de script est fourni et qu'il s'agit d'un fichier, l'entrée de variable est affectée au nom du fichier. S'il n'y a pas d'argument valide, cat lit depuis le clavier.
la source
&& input="$1" || input="-"
-il et pourquoi est-il en dehors de l'test
opérateur?$@
)?read
lit à partir de l'entrée standard. Le rediriger depuis file (./script <someinput
) ou via pipe (dosomething | ./script
) ne le fera pas fonctionner différemment.Tout ce que vous avez à faire est de parcourir toutes les lignes en entrée (et cela ne diffère pas d’itérer sur les lignes du fichier).
(exemple de code, traite une seule ligne)
Répondra à la première ligne de votre entrée standard (via
<
ou|
).la source
Vous ne mentionnez pas le shell que vous comptez utiliser, alors je suppose que bash, bien que ce soient des choses assez standard pour tous les obus.
Arguments de fichier
Les arguments sont accessibles via les variables
$1
-$n
($0
retourne la commande utilisée pour exécuter le programme). Supposons que j’ai un script quicat
contient un nombre n de fichiers avec un séparateur entre eux:Dans ce cas, nous passons un nom de fichier à cat. Toutefois, si vous souhaitez transformer les données du fichier (sans les écrire ni les réécrire explicitement), vous pouvez également stocker le contenu du fichier dans une variable:
Lire de stdin
En ce qui concerne stdin, la plupart des interpréteurs ont un standard assez
read
intégré, bien qu'il existe des différences dans la manière dont les invites sont spécifiées (au moins).La page de manuel de Bash builtins contient une explication assez concise
read
, mais je préfère la page Bash Hackers .Simplement:
Plusieurs variables
Pour définir plusieurs variables, indiquez simplement plusieurs noms de paramètres
read
:read
placera ensuite un mot de stdin dans chaque variable, vidant tous les mots restants dans la dernière variable.Si moins de mots sont entrés que de variables, les variables restantes seront vides (même si elles avaient été définies précédemment):
Instructions
J'utilise
-p
souvent flag pour une invite:Remarque: ZSH et KSH (et peut-être d'autres) utilisent une syntaxe différente pour les invites:
Les valeurs par défaut
Ce n'est pas vraiment une
read
ruse, mais je l'utilise beaucoup en conjonction avecread
. Par exemple:En gros, si la variable (réponse) existe, retourne elle-même, mais si est vide, retourne le paramètre suivant ("N").
la source
Le moyen le plus simple est de rediriger stdin vous-même:
Ou si vous préférez la forme plus laconique:
Maintenant, le reste de votre script peut simplement lire à partir de stdin. Bien sûr, vous pouvez faire de même avec une analyse d’options plus avancée plutôt que de coder en dur la position du nom de fichier comme
"$1"
.la source
exec
essaierons d'exécuter l'argument comme une commande qui n'est pas ce que nous voulons ici.if [ "$1" ] ; then exec < "$1" ; fi
dans un script de test et cela donne un message d'erreur parce que la commande est inconnue. Même avec la forme laconique.utiliser (ou enchaîner) quelque chose d'autre qui se comporte déjà de cette façon, et utiliser
"$@"
disons que je veux écrire un outil qui remplacera des séries d'espaces dans le texte avec des onglets
tr
est la façon la plus évidente de le faire, mais il n'accepte stdin, nous avons donc à la chaîne hors de :cat
pour un exemple où l'outil utilisé se comporte déjà de cette façon, nous pourrions le réimplémenter avec à la
sed
place:la source
Vous pouvez aussi faire:
Pour plus d’astuces de substitution de paramètres dans Bash, voyez ceci .
la source
uglifyjs < /dev/stdin
et ça marche à merveille!Vous pouvez également rester simple et utiliser ce code
Lorsque vous créez un fichier de script pass_it_on.sh avec ce code,
Tu peux courir
et tout le contenu de stdin sera simplement diffusé à l'écran.
Vous pouvez également utiliser ce code pour conserver une copie de stdin dans un fichier, puis la cracher à l'écran.
et voici un autre exemple, peut-être plus lisible, expliqué ici:
http://mockingeye.com/blog/2013/01/22/reading-everything-stdin-in-a-bash-script/
S'amuser.
RaamEE
la source
Le moyen le plus simple et compatible POSIX est:
ce qui équivaut à
${1:--}
.Ensuite, lisez le fichier comme d'habitude:
la source