{"id":82,"date":"2014-08-30T21:57:18","date_gmt":"2014-08-30T21:57:18","guid":{"rendered":"https:\/\/www.aya.io\/ayablog\/?p=82"},"modified":"2022-02-06T21:57:36","modified_gmt":"2022-02-06T21:57:36","slug":"ruby-stdin-argv-argf","status":"publish","type":"post","link":"https:\/\/www.aya.io\/blog\/ruby-stdin-argv-argf\/","title":{"rendered":"Ruby : STDIN, ARGV et ARGF"},"content":{"rendered":"<p>Quand on d\u00e9bute en Ruby, on peut se demander comment r\u00e9unir dans un seul script les comportements de base d'une application compatible Unix&nbsp;:<\/p>\n<ul>\n<li>\n<p>accepte des param\u00e8tres de commande<\/p>\n<\/li>\n<li>\n<p>accepte des donn\u00e9es en entr\u00e9e<\/p>\n<\/li>\n<li>\n<p>accepte des fichiers en param\u00e8tres ou en entr\u00e9e<\/p>\n<\/li>\n<\/ul>\n<p>Nous allons voir comment g\u00e9rer \u00e7a de mani\u00e8re simplissime dans un petit script.<\/p>\n<p><!-- more --><\/p>\n<p>Pour une application d'envergure il vaut mieux passer par une Gem d\u00e9di\u00e9e qui va parser les param\u00e8tres pour vous, de type Thor, mais pour un script modeste ces solutions sont tr\u00e8s rapides et pratiques.<\/p>\n<h1>Param\u00e8tres<\/h1>\n<h2>Arguments<\/h2>\n<p>Ruby fournit la constante <code>ARGV<\/code> qui est un tableau (<em>array<\/em>) contenant les arguments fournis lors de l'appel du script.<\/p>\n<ul>\n<li><em>myscript.rb&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-ruby\">puts ARGV.inspect<\/code><\/pre>\n<ul>\n<li><em>Commande&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\">ruby myscript.rb --help &#039;ma commande&#039;<\/code><\/pre>\n<ul>\n<li><em>R\u00e9sultat&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\"># [&quot;--help&quot;, &quot;ma commande&quot;]<\/code><\/pre>\n<p>C'est vraiment la base&nbsp;:<\/p>\n<pre><code class=\"language-ruby\">if ARGV[0] == &#039;--help&#039;\n  puts &quot;Besoin d&#039;aide \u00e0 propos de &#039;#{ARGV[1]}&#039; ?&quot;\nelse\n  puts &quot;Tout va bien.&quot;\nend<\/code><\/pre>\n<p>Ca ne va pas bien loin avant d'\u00eatre totalement fastidieux et labyrinthique, mais \u00e7a suffit pour deux ou trois options.<\/p>\n<h2>Arguments ou Fichiers ?<\/h2>\n<p>Exemple un tout petit peu plus avanc\u00e9.<\/p>\n<p>Disons qu'on accepte une option <code>--file<\/code> qui fournit un fichier texte \u00e0 lire, ou alors pas d'option et on affiche la liste index\u00e9e des arguments s'il y en a.<\/p>\n<p>Nous allons utiliser la constante <code>ARGF<\/code> fournie par Ruby, c'est elle qui re\u00e7oit les fichiers pass\u00e9s en argument.<\/p>\n<p>Cr\u00e9ez un fichier d'exemple si vous le souhaitez&nbsp;:<\/p>\n<pre><code class=\"language-text\">$ echo &quot;hihiahahohoh&quot; &gt; ahah.txt<\/code><\/pre>\n<ul>\n<li><em>myscript.rb&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-ruby\">if ARGV.empty?\n  puts &quot;Rien. Le vide. Le silence.&quot;\nelsif ARGV[0] == &quot;--file&quot;\n  ARGV.shift\n  puts &quot;Contenu du fichier:&quot;\n  puts ARGF.read\nelse\n  ARGV.each.with_index(1) {|arg, index| puts &quot;Arg #{index}: #{arg}&quot;}\nend<\/code><\/pre>\n<ul>\n<li><em>Commande&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\">$ ruby myscript.rb<\/code><\/pre>\n<ul>\n<li><em>R\u00e9sultat&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\"># Rien. Le vide. Le silence.<\/code><\/pre>\n<ul>\n<li><em>Commande&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\">$ ruby myscript.rb --file ahah.txt<\/code><\/pre>\n<ul>\n<li><em>R\u00e9sultat&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\"># Contenu du fichier:\n# hihiahahohoh<\/code><\/pre>\n<ul>\n<li><em>Commande&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\">$ ruby myscript.rb ok allo voil\u00e0<\/code><\/pre>\n<ul>\n<li><em>R\u00e9sultat&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\"># Arg 1: ok\n# Arg 2: allo\n# Arg 3: voil\u00e0<\/code><\/pre>\n<p><em>Note: je n'indiquerai plus la commande de l'interpr\u00e9teur Ruby, mais vais consid\u00e9rer que vous avez rendu votre script ex\u00e9cutable.<\/em><\/p>\n<blockquote>\n<p>Ajoutez la ligne <code>#!\/usr\/bin\/env ruby<\/code> au d\u00e9but du script, puis rendez le script ex\u00e9cutable dans votre shell: <code>chmod u+x myscript.rb<\/code>. Plus besoin de lancer le script avec <code>ruby myscript.rb<\/code>, il suffira de faire <code>.\/myscript.rb<\/code>.<\/p>\n<\/blockquote>\n<h1>En entr\u00e9e<\/h1>\n<p>On peut aussi vouloir accepter des donn\u00e9es en entr\u00e9e, comme par exemple avec le pipe du shell.<\/p>\n<p>C'est la constante <code>STDIN<\/code> qui va nous fournir cette possibilit\u00e9.<\/p>\n<ul>\n<li><em>myscript.rb&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-ruby\">#!\/usr\/bin\/env ruby\nputs &quot;Vous avez indiqu\u00e9:&quot;\nputs STDIN.read<\/code><\/pre>\n<ul>\n<li><em>Commande&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\">$ echo &#039;ohl\u00e0l\u00e0&#039; | .\/myscript.rb<\/code><\/pre>\n<ul>\n<li><em>R\u00e9sultat&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\"># Vous avez indiqu\u00e9:\n# ohl\u00e0l\u00e0<\/code><\/pre>\n<ul>\n<li><em>Commande&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\">$ cat ahah.txt | .\/myscript.rb<\/code><\/pre>\n<ul>\n<li><em>R\u00e9sultat&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\"># Vous avez indiqu\u00e9:\n# hihiahahohoh<\/code><\/pre>\n<p>Ca marche aussi dans l'autre sens avec le chevron&nbsp;!<\/p>\n<ul>\n<li><em>Commande&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\">$ .\/myscript.rb &lt; ahah.txt<\/code><\/pre>\n<ul>\n<li><em>R\u00e9sultat&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-text\"># Vous avez indiqu\u00e9:\n# hihiahahohoh<\/code><\/pre>\n<h1>Ensemble<\/h1>\n<p>Et maintenant, voyons un petit ensemble de conditions pour d\u00e9terminer dans notre script de quelle fa\u00e7on les donn\u00e9es ont \u00e9t\u00e9 re\u00e7ues.<\/p>\n<p>Nous utilisons les contantes d\u00e9j\u00e0 vues plus haut, ainsi que la variable globale <code>$stdin<\/code> qui repr\u00e9sente l'\u00e9tat du Terminal.<\/p>\n<ul>\n<li><em>myscript.rb&nbsp;:<\/em><\/li>\n<\/ul>\n<pre><code class=\"language-ruby\">#!\/usr\/bin\/env ruby\nif $stdin.tty?\n  if ARGV.empty?\n    puts &quot;Rien. Le vide. Le silence.&quot;\n  elsif ARGV[0] == &#039;--file&#039; || ARGV[0] == &#039;-F&#039;\n    ARGV.shift\n    puts &quot;Contenu du fichier:&quot;\n    puts ARGF.read\n  else\n    ARGV.each.with_index(1) {|arg, index| puts &quot;Arg #{index}: #{arg}&quot;}\n  end\nelse\n  puts &quot;Vous avez indiqu\u00e9:&quot;\n  puts STDIN.read\nend<\/code><\/pre>\n<p>Avec <code>if $stdin.tty?<\/code> nous demandons si nous venons de recevoir des arguments apr\u00e8s la commande.<\/p>\n<p>Dans cette condition nous utilisons <code>ARGV<\/code> pour les arguments et <code>ARGF<\/code> pour les fichiers.<\/p>\n<p>Si pas d'arguments fournis, l'autre branche de la condition lit les donn\u00e9es en entr\u00e9e avec <code>STDIN.read<\/code>.<\/p>\n<p><em>Tous les exemples de commande vus plus haut, que ce soient les arguments, les fichiers, le pipe ou le chevron, fonctionnent avec ce simple script.<\/em><\/p>\n<h1>Conclusion<\/h1>\n<p>Cet aper\u00e7u des m\u00e9thodes pour recevoir diff\u00e9rentes donn\u00e9es dans vos scripts Ruby \u00e9tait volontairement simple, le but \u00e9tait de r\u00e9pondre aux questions les plus fr\u00e9quentes.<\/p>\n<p>Mais n'oubliez pas d'utiliser une Gem d\u00e9di\u00e9e si vous avez plus de deux ou trois options \u00e0 traiter, ce sera bien plus puissant et modulable.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Quand on d\u00e9bute en Ruby, on peut se demander comment r\u00e9unir dans un seul script les comportements de base d&rsquo;une application compatible Unix&nbsp;: accepte des param\u00e8tres de commande accepte des donn\u00e9es en entr\u00e9e accepte des fichiers en param\u00e8tres ou en entr\u00e9e Nous allons voir comment g\u00e9rer \u00e7a de mani\u00e8re simplissime dans un petit script. Pour&hellip; <a class=\"more-link\" href=\"https:\/\/www.aya.io\/blog\/ruby-stdin-argv-argf\/\">Poursuivre la lecture <span class=\"screen-reader-text\">Ruby : STDIN, ARGV et ARGF<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":83,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,24,10],"tags":[],"class_list":["post-82","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev","category-ruby","category-tuto","entry"],"_links":{"self":[{"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/posts\/82","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/comments?post=82"}],"version-history":[{"count":2,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/posts\/82\/revisions"}],"predecessor-version":[{"id":85,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/posts\/82\/revisions\/85"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/media\/83"}],"wp:attachment":[{"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/media?parent=82"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/categories?post=82"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.aya.io\/blog\/wp-json\/wp\/v2\/tags?post=82"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}