1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
<h1 id="optparse-command-line-option-parsing">optparse Command Line Option Parsing</h1>
<p>optparse is a command line option parser inspired by Python's "optparse" library. Use this with Rscript to write "#!"-shebang scripts that accept short and long flags/options, generate a usage statement, and set default values for options that are not specified on the command line.</p>
<p>In our working directory we have two example R scripts, named "example.R" and "display_file.R" illustrating the use of the optparse package.</p>
<p><strong>bash$ ls</strong></p>
<pre><code>display_file.R
example.R</code></pre>
<p>In order for a *nix system to recognize a "#!"-shebang line you need to mark the file executable with the <code>chmod</code> command, it also helps to add the directory containing your Rscripts to your path:</p>
<p><strong>bash$ chmod ug+x display_file.R example.R</strong></p>
<p><strong>bash$ export PATH=$PATH:`pwd`</strong></p>
<p>Here is what <code>example.R</code> contains:</p>
<p><strong>bash$ display_file.R example.R</strong></p>
<pre><code>#!/usr/bin/env Rscript
# Copyright 2010-2013 Trevor L Davis <trevor.l.davis@gmail.com>
# Copyright 2008 Allen Day
#
# This file is free software: you may copy, redistribute and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 2 of the License, or (at your
# option) any later version.
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
suppressPackageStartupMessages(library("optparse"))
suppressPackageStartupMessages(library("stats"))
# specify our desired options in a list
# by default OptionParser will add an help option equivalent to
# make_option(c("-h", "--help"), action="store_true", default=FALSE,
# help="Show this help message and exit")
option_list <- list(
make_option(c("-v", "--verbose"), action="store_true", default=TRUE,
help="Print extra output [default]"),
make_option(c("-q", "--quietly"), action="store_false",
dest="verbose", help="Print little output"),
make_option(c("-c", "--count"), type="integer", default=5,
help="Number of random normals to generate [default %default]",
metavar="number"),
make_option("--generator", default="rnorm",
help = "Function to generate random deviates [default \"%default\"]"),
make_option("--mean", default=0,
help="Mean if generator == \"rnorm\" [default %default]"),
make_option("--sd", default=1, metavar="standard deviation",
help="Standard deviation if generator == \"rnorm\" [default %default]")
)
# get command line options, if help option encountered print help and exit,
# otherwise if options not found on command line then set defaults,
opt <- parse_args(OptionParser(option_list=option_list))
# print some progress messages to stderr if "quietly" wasn't requested
if ( opt$verbose ) {
write("writing some verbose output to standard error...\n", stderr())
}
# do some operations based on user input
if( opt$generator == "rnorm") {
cat(paste(rnorm(opt$count, mean=opt$mean, sd=opt$sd), collapse="\n"))
} else {
cat(paste(do.call(opt$generator, list(opt$count)), collapse="\n"))
}
cat("\n")</code></pre>
<p>By default <em>optparse</em> will generate a help message if it encounters <code>--help</code> or <code>-h</code> on the command line. Note how <code>%default</code> in the example program was replaced by the actual default values in the help statement that <em>optparse</em> generated.</p>
<p><strong>bash$ example.R --help</strong></p>
<pre><code>Usage: example.R [options]
Options:
-v, --verbose
Print extra output [default]
-q, --quietly
Print little output
-c NUMBER, --count=NUMBER
Number of random normals to generate [default 5]
--generator=GENERATOR
Function to generate random deviates [default "rnorm"]
--mean=MEAN
Mean if generator == "rnorm" [default 0]
--sd=STANDARD DEVIATION
Standard deviation if generator == "rnorm" [default 1]
-h, --help
Show this help message and exit</code></pre>
<p>If you specify default values when creating your <code>OptionParser</code> then <em>optparse</em> will use them as expected.</p>
<p><strong>bash$ example.R</strong></p>
<pre><code>writing some verbose output to standard error...
-1.0319088787312
1.51467317739761
-0.182264759789326
0.250964592323344
2.39012966005878</code></pre>
<p>Or you can specify your own values.</p>
<p><strong>bash$ example.R --mean=10 --sd=10 --count=3</strong></p>
<pre><code>writing some verbose output to standard error...
-5.8641068053515
5.00111136905801
-3.86971764740004</code></pre>
<p>If you remember from the example program that <code>--quiet</code> had <code>action="store_false"</code> and <code>dest="verbose"</code>. This means that <code>--quiet</code> is a switch that turns the <code>verbose</code> option from its default value of <code>TRUE</code> to <code>FALSE</code>. Note how the <code>verbose</code> and <code>quiet</code> options store their value in the exact same variable.</p>
<p><strong>bash$ example.R --quiet -c 4 --generator="runif"</strong></p>
<pre><code>0.0934223954100162
0.347937157377601
0.262309876270592
0.867103962693363</code></pre>
<p>If you specify an illegal flag then <em>optparse</em> will throw an error.</p>
<p><strong>bash$ example.R --silent -m 5</strong></p>
<pre><code>Usage: example.R [options]
example.R: error: Error in getopt(spec = spec, opt = args) : long flag "silent" is invalid</code></pre>
<p>If you specify the same option multiple times then <em>optparse</em> will use the value of the last option specified.</p>
<p><strong>bash$ example.R -c 100 -c 2 -c 1000 -c 7</strong></p>
<pre><code>writing some verbose output to standard error...
-0.356474119252246
-0.542733697176872
0.350193368905548
0.315063370156928
-1.03597296782789
-0.119909869407653
2.20846228253079</code></pre>
<p><em>optparse</em> can also recognize positional arguments if <code>parse_args</code> is given the option <code>positional_arguments = c(min_pa, max_pa)</code> where <code>min_pa</code> is the minimum and <code>max_pa</code> is the maximum number of supported positional arguments. (A single numeric corresponds to <code>min_pa == max_pa</code>, <code>TRUE</code> is equivalent to <code>c(0, Inf)</code>, and <code>FALSE</code>, the default, is equivalent to <code>0</code>.) Below we give an example program <em>display_file.R</em>, which is a program that prints out the contents of a single file (the required positional argument, not an optional argument) and which accepts the normal help option as well as an option to add line numbers to the output. Note that the positional arguments need to be placed <em>after</em> the optional arguments.</p>
<p><strong>bash$ display_file.R --help</strong></p>
<pre><code>Usage: display_file.R [options] file
Options:
-n, --add_numbers
Print line number at the beginning of each line [default]
-h, --help
Show this help message and exit</code></pre>
<p><strong>bash$ display_file.R --add_numbers display_file.R</strong></p>
<pre><code>1 #!/usr/bin/env Rscript
2 # Copyright 2010-2013 Trevor L Davis <trevor.l.davis@gmail.com>
3 # Copyright 2013 Kirill Müller
4 #
5 # This file is free software: you may copy, redistribute and/or modify it
6 # under the terms of the GNU General Public License as published by the
7 # Free Software Foundation, either version 2 of the License, or (at your
8 # option) any later version.
9 #
10 # This file is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
17 suppressPackageStartupMessages(library("optparse"))
18
19 option_list <- list(
20 make_option(c("-n", "--add_numbers"), action="store_true", default=FALSE,
21 help="Print line number at the beginning of each line [default]")
22 )
23 parser <- OptionParser(usage = "%prog [options] file", option_list=option_list)
24
25 arguments <- parse_args(parser, positional_arguments = 1)
26 opt <- arguments$options
27 file <- arguments$args
28
29 if( file.access(file) == -1) {
30 stop(sprintf("Specified file ( %s ) does not exist", file))
31 } else {
32 file_text <- readLines(file)
33 }
34
35 if(opt$add_numbers) {
36 cat(paste(1:length(file_text), file_text), sep = "\n")
37 } else {
38 cat(file_text, sep = "\n")
39 }</code></pre>
<p><strong>bash$ display_file.R non_existent_file.txt</strong></p>
<pre><code>Error: Specified file ( non_existent_file.txt ) does not exist
Execution halted</code></pre>
<p><strong>bash$ display_file.R</strong></p>
<pre><code>Usage: display_file.R [options] file
display_file.R: error: required at least 1 positional arguments, got 0</code></pre>
|