Reputation: 1278
I have the following R script for which I have added comments to make a simple example with cars of what I am trying to achieve:
#!/usr/bin/env Rscript
# the arguments come in this way:
# args[1] is a file containing the maximum speeds of different cars (one per line)
# args[2] is the title that the plot will have
# args[3] contains the horsepower of the engine of the first car in args[1] (the lowest)
# args[4] contains the horsepower of the engine of the last car in args[1] (the highest)
# NOTE1: the speeds in args[1] must be listed starting from the car
# with the lowest horsepower to the car with the highest horsepower
# NOTE2: in args[1], a car must differ from the next one by 1 horsepower, i.e., if
# there are 5 speeds, and the horsepower of the first car in the file is 30, then the
# the horsepower of the second one must be 31, the third one 32, .... the fifth one must
# be 34.
args<-commandArgs(TRUE)
# creating the vector with the horsepower of each car
horsepowers = numeric()
for (i in args[3]:args[4]) {
horsepowers = c(horsepowers,i)
}
# reading file with speeds and getting vector with speeds
speeds <- read.csv(file=args[1],head=FALSE,sep="\n")$V1
# creating plot with speeds in previous vector
outputTitle = gsub(" ","", args[2] , fixed=TRUE)
pdf(paste(outputTitle, ".pdf", sep = ""))
plot(horsepowers, speeds, type="o", col="red", xlab="horsepowers", ylab="speeds")
# giving a title to the plot
title(main=args[2], col.main="Black")
I have a sample file called myFile
with speeds of 5 cars that looks like this
150
156
157
161
164
And suppose that the horsepower of the first car is 30 so that would make the horsepower of the last car 34 (remember that the first speed corresponds to the car with the lowest horsepower, the second one to the car with the next to lowest horsepower, and so on; and the cars must differ by 1 horsepower, otherwise the for loop in the script would not make sense). So if I run the script in the command line like this:
./myPlotter.R myFile "My Title" 30 34
it works fine and makes the plot (I cropped the y label, x label, and title just because they don't match with the car example above but the script used is the same, I just changed the variable names for the car example):
However, when called from the following bash script:
#!/bin/bash
while getopts ":a:1:2:3:4" arg; do
case "$arg" in
a)
option=$OPTARG
;;
1)
fileWithSpeeds=$OPTARG
;;
2)
titleOfGraph=$OPTARG
;;
3)
lowestHP=$OPTARG
;;
4)
highestHP=$OPTARG
;;
esac
done
# I do not think that this if statement makes any difference for this example
# but I left it there just in case
if [ $option == "option1" ]; then
./myPlotter.R $fileWithSpeeds $titleOfGraph $lowestHP $highestHP
fi
in this way:
./bashPlot.sh -a option1 -1 myFile -2 "My Title" -3 30 -4 34
I get the following error:
Error in args[3]:args[4] : NA/NaN argument
Execution halted
What is causing this?
Summary: I have an R script that works fine when called from the command line but gives an error when called from a bash script with arguments gotten from getopts.
Upvotes: 1
Views: 116
Reputation: 124734
The bug is in the getots
string, instead of this:
while getopts ":a:1:2:3:4" arg; do
It should be like this:
while getopts "a:1:2:3:4:" arg; do
You could see the problem by echoing the command that executes the R script:
echo "./myPlotter.R $fileWithSpeeds $titleOfGraph $lowestHP $highestHP"
./myPlotter.R $fileWithSpeeds $titleOfGraph $lowestHP $highestHP
You could see from the output that the $highestHP
parameter was always blank.
You don't need the double quotes here:
if [ $option == "option1" ]; then
And the [ ... ]
operator is now obsoleted, use [[ ... ]]
instead, like this:
if [[ $option == option1 ]]; then
Upvotes: 2