Reputation: 2879
I know this is a simple question and I have been examining the getopts tutorials and examples, but I am stuck. If you check this link, you will see that with the help of @fedorqui, I have managed to write the code in order to get an element of an array in a file.
However, what I need is to parameterize the inputs so that the script will continue to work even if I change the order of inputs.
This is the first code I wrote:
#!/bin/bash
file=$3 row=$1 col=$2 str1="Hata: " str2=". satır " str3=". sütun yok"
if [ $row -gt 3 ]
then
echo $str1$row$str2$col$str3
elif [ $col -gt 3 ]
then
echo $str1$row$str2$col$str3
else
awk 'NR==row{print $col}' row=$row col=$col $file
fi
Now, the script works like $ ./tablooku.sh 3 2 tablom.dat
and the output is:
~/Desktop $ ./tablooku.sh 3 2 tablom.dat
Kopenhag
What I need to do is to translate this code so that when I enter $ ./tablooku.sh -r 3 -c 2 tablom.dat
, I get the script work.
This is the code I wrote which stucks upon running:
#!/bin/bash
str1="Hata: "
str2=". satır "
str3=". sütun yok"
while getopts "r:c:f:" opts
do
case $opts in
r) row=$OPTARG echo "-r was triggered, Parameter: $OPTARG";;
c) col=$OPTARG echo "-c was triggered, Parameter: $OPTARG";;
f) fi=$OPTARG echo "-f was triggered, Parameter: $OPTARG";;
\?) printf "Kullanım: %s -r değer -c değer dosya adresi\n" $0
exit 2;;
esac
done
if [ $row -gt 3 ]
then
echo $str1$row$str2$col$str3
elif [ $col -gt 3 ]
then
echo $str1$row$str2$col$str3
else
awk 'NR==r{print $c}' r=$row c=$col $fi
fi
Can you please tell me what is wrong here? When I run the command the system output is:
~/Desktop $ ./go_test.sh -r 3 -c 2 tablom.dat
-r was triggered, Parameter: 3
-c was triggered, Parameter: 2
./go_test.sh: line 23: [: -gt: unary operator expected
./go_test.sh: line 26: [: -gt: unary operator expected
The prompt stucks and I have to use ctrl+z
to break the waiting. It looks like I am failing to assign the file location to fi
but I could not solve the problem
Note: Please remember -r is row, - c is column and the last parameter is the file location which does not use any option code (such as -f)
UPDATE 1:
I changed the if brackets ]
with ]]
and [
with [[
. Now the unary operator expected
error is gone. Now, the prompt waits and does not print -f was triggered, Parameter:...
I still use ctrl+z
to break the waiting.
UPDATE 2:
With the suggestion of both @grebneke and @TimK, I added the semi-colons and changed the fi
parameter to fil
. This way, I get the script working. However, there is one little problem remaining. The code works if I enter $ ./tablooku.sh -r 3 -c 2 -f tablom.dat
. However, I need it to run without having to write -f
. Is it possible?
Upvotes: 0
Views: 433
Reputation: 4494
In these lines:
r) row=$OPTARG echo "-r was triggered, Parameter: $OPTARG";;
c) col=$OPTARG echo "-c was triggered, Parameter: $OPTARG";;
f) fi=$OPTARG echo "-f was triggered, Parameter: $OPTARG";;
You are assigning row/col/fi
for the remainder of the line only. Add a semicolon after the assignment and it will stay assigned for the rest of the script:
r) row=$OPTARG; echo "-r was triggered, Parameter: $OPTARG";;
c) col=$OPTARG; echo "-c was triggered, Parameter: $OPTARG";;
f) fi=$OPTARG; echo "-f was triggered, Parameter: $OPTARG";;
Edit <deleted, I misunderstood the question>
Edit 2
To get the remaining arguments after using getopts
, you must shift
like this:
while getopts "r:c:" opts
do
...
done
shift $(( $OPTIND-1 ))
# Now, $1, $2 etc are your arguments as you are used to:
$ ./tablooku.sh -r 3 -c 2 tablom.dat
# $1 will be "tablom.dat"
Upvotes: 1
Reputation: 6120
You're missing a semi-colon in where you're setting $row, $col, and $fi.
case $opts in
r) row=$OPTARG echo "-r was triggered, Parameter: $OPTARG";;
c) col=$OPTARG echo "-c was triggered, Parameter: $OPTARG";;
f) fi=$OPTARG echo "-f was triggered, Parameter: $OPTARG";;
\?) printf "Kullanım: %s -r değer -c değer dosya adresi\n" $0
exit 2;;
esac
Should be (semi-colon before the echo
):
case $opts in
r) row=$OPTARG ; echo "-r was triggered, Parameter: $OPTARG";;
c) col=$OPTARG ; echo "-c was triggered, Parameter: $OPTARG";;
f) fi=$OPTARG ; echo "-f was triggered, Parameter: $OPTARG";;
\?) printf "Kullanım: %s -r değer -c değer dosya adresi\n" $0
exit 2;;
esac
Without those semi-colons, your commands are not being run as you would expect, as you can see looking at the output of bash -x, and examine the lines with -gt:
bash-[576]$ bash -x foo.bash -r 3 -c 3 -f foo
+ str1='Hata: '
+ str2='. satır '
+ str3='. sütun yok'
+ getopts r:c:f: opts
+ case $opts in
+ row=3
+ echo '-r was triggered, Parameter: 3'
-r was triggered, Parameter: 3
+ getopts r:c:f: opts
+ case $opts in
+ col=3
+ echo '-c was triggered, Parameter: 3'
-c was triggered, Parameter: 3
+ getopts r:c:f: opts
+ case $opts in
+ fi=foo
+ echo '-f was triggered, Parameter: foo'
-f was triggered, Parameter: foo
+ getopts r:c:f: opts
+ '[' -gt 3 ']'
foo.bash: line 18: [: -gt: unary operator expected
+ '[' -gt 3 ']'
foo.bash: line 20: [: -gt: unary operator expected
+ awk 'NR==r{print $c}' r= c=
With the semi-colons:
bash-[574]$ bash -x foo.bash -r 3 -c 3 -f foo
+ str1='Hata: '
+ str2='. satır '
+ str3='. sütun yok'
+ getopts r:c:f: opts
+ case $opts in
+ row=3
+ echo '-r was triggered, Parameter: 3'
-r was triggered, Parameter: 3
+ getopts r:c:f: opts
+ case $opts in
+ col=3
+ echo '-c was triggered, Parameter: 3'
-c was triggered, Parameter: 3
+ getopts r:c:f: opts
+ case $opts in
+ fi=foo
+ echo '-f was triggered, Parameter: foo'
-f was triggered, Parameter: foo
+ getopts r:c:f: opts
+ '[' 3 -gt 3 ']'
+ '[' 3 -gt 3 ']'
+ awk 'NR==r{print $c}' r=3 c=3 foo
Again, look at the lines with -gt. So your variable settings of $row, $col, and $fi are not propagating without the ;
.
Upvotes: 0