Binary operator expected - quoting question for shell script args
Clash Royale CLAN TAG#URR8PPP
up vote
1
down vote
favorite
I have a question on how I'm adding arguments when executing a shell script.
I have a simple script which helps me block ip ranges:
~/block_ip.sh:
if [ ! $3 ]
then
echo "usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'"
exit 1
fi
echo "adding $3"
sudo iptables -I INPUT -s $2 -j $1 -m comment --comment "$3"
If I execute this without arguments the output is as expected:
~$ ./block_ip.sh
usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'
However the spaces seem to be the cause of the unexpected output of "binary operator expected":
~$ ./block_ip.sh DROP '1.0.0.0/8' 'south brisbane qld'
./block_ip.sh: line 1: [: brisbane: binary operator expected
adding south brisbane au
But then it adds it despite the unexpected output:
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 1.0.0.0/8 anywhere /* south brisbane au */
If this is a quoting issue, how do I form the arguments (without using backslashes to escape the spaces)? Of course, I expect I may need a change to the script, that is an acceptable solution, too.
bash shell-script arguments whitespace
add a comment |Â
up vote
1
down vote
favorite
I have a question on how I'm adding arguments when executing a shell script.
I have a simple script which helps me block ip ranges:
~/block_ip.sh:
if [ ! $3 ]
then
echo "usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'"
exit 1
fi
echo "adding $3"
sudo iptables -I INPUT -s $2 -j $1 -m comment --comment "$3"
If I execute this without arguments the output is as expected:
~$ ./block_ip.sh
usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'
However the spaces seem to be the cause of the unexpected output of "binary operator expected":
~$ ./block_ip.sh DROP '1.0.0.0/8' 'south brisbane qld'
./block_ip.sh: line 1: [: brisbane: binary operator expected
adding south brisbane au
But then it adds it despite the unexpected output:
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 1.0.0.0/8 anywhere /* south brisbane au */
If this is a quoting issue, how do I form the arguments (without using backslashes to escape the spaces)? Of course, I expect I may need a change to the script, that is an acceptable solution, too.
bash shell-script arguments whitespace
1
If your goal in testing$3
is just to be sure that there are three parameters, then you can use the simpler$#
shell variable, which holds the number of parameters, eg.if [ $# -ne 3 ]
.
â user1404316
Feb 8 at 17:45
@user1404316 very useful - thanks
â WEBjuju
Feb 8 at 21:10
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I have a question on how I'm adding arguments when executing a shell script.
I have a simple script which helps me block ip ranges:
~/block_ip.sh:
if [ ! $3 ]
then
echo "usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'"
exit 1
fi
echo "adding $3"
sudo iptables -I INPUT -s $2 -j $1 -m comment --comment "$3"
If I execute this without arguments the output is as expected:
~$ ./block_ip.sh
usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'
However the spaces seem to be the cause of the unexpected output of "binary operator expected":
~$ ./block_ip.sh DROP '1.0.0.0/8' 'south brisbane qld'
./block_ip.sh: line 1: [: brisbane: binary operator expected
adding south brisbane au
But then it adds it despite the unexpected output:
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 1.0.0.0/8 anywhere /* south brisbane au */
If this is a quoting issue, how do I form the arguments (without using backslashes to escape the spaces)? Of course, I expect I may need a change to the script, that is an acceptable solution, too.
bash shell-script arguments whitespace
I have a question on how I'm adding arguments when executing a shell script.
I have a simple script which helps me block ip ranges:
~/block_ip.sh:
if [ ! $3 ]
then
echo "usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'"
exit 1
fi
echo "adding $3"
sudo iptables -I INPUT -s $2 -j $1 -m comment --comment "$3"
If I execute this without arguments the output is as expected:
~$ ./block_ip.sh
usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'
However the spaces seem to be the cause of the unexpected output of "binary operator expected":
~$ ./block_ip.sh DROP '1.0.0.0/8' 'south brisbane qld'
./block_ip.sh: line 1: [: brisbane: binary operator expected
adding south brisbane au
But then it adds it despite the unexpected output:
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 1.0.0.0/8 anywhere /* south brisbane au */
If this is a quoting issue, how do I form the arguments (without using backslashes to escape the spaces)? Of course, I expect I may need a change to the script, that is an acceptable solution, too.
bash shell-script arguments whitespace
edited Feb 8 at 15:52
ilkkachu
49.6k673137
49.6k673137
asked Feb 8 at 15:47
WEBjuju
410211
410211
1
If your goal in testing$3
is just to be sure that there are three parameters, then you can use the simpler$#
shell variable, which holds the number of parameters, eg.if [ $# -ne 3 ]
.
â user1404316
Feb 8 at 17:45
@user1404316 very useful - thanks
â WEBjuju
Feb 8 at 21:10
add a comment |Â
1
If your goal in testing$3
is just to be sure that there are three parameters, then you can use the simpler$#
shell variable, which holds the number of parameters, eg.if [ $# -ne 3 ]
.
â user1404316
Feb 8 at 17:45
@user1404316 very useful - thanks
â WEBjuju
Feb 8 at 21:10
1
1
If your goal in testing
$3
is just to be sure that there are three parameters, then you can use the simpler $#
shell variable, which holds the number of parameters, eg. if [ $# -ne 3 ]
.â user1404316
Feb 8 at 17:45
If your goal in testing
$3
is just to be sure that there are three parameters, then you can use the simpler $#
shell variable, which holds the number of parameters, eg. if [ $# -ne 3 ]
.â user1404316
Feb 8 at 17:45
@user1404316 very useful - thanks
â WEBjuju
Feb 8 at 21:10
@user1404316 very useful - thanks
â WEBjuju
Feb 8 at 21:10
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
5
down vote
accepted
Yep, that's a quoting issue: [ ! $3 ]
expands to [ ! south brisbane qld ]
(four arguments between [
and ]
). And when it sees four arguments, with the first one a !
, [
expects to see something like [ ! arg1 op arg2 ]
where op
is a binary operator. (this, again is one of the things different between [ .. ]
and [[ .. ]]
; see this Q and also this Q)
brisbane
isn't a valid operator, so it complains and returns 2, which is falsy so the statements inside the if
are not executed. To tell the difference between an error and a regular failing test, you'd need to explicitly test the return value against 2.
On the other hand, if $3
is empty, then the test becomes [ ! ]
, a one-argument test that checks if the only argument is nonempty (it is, it's the one-character string !
). In that case, it works as intended, though perhaps not for the reason you'd expect.
You want [ ! "$3" ]
or [ -z "$3" ]
to keep the string as one argument for [
.
Of course you could also invert the sense of the test, and do the actual work inside the if
, so that an error in the test would avoid running the main commands. But that would make the code structure a bit more unclear.
nice - so the reason it is working then is that even though it errors, $3 isn't empty so it passes the ! test and then i have it quoted in theiptables
command so its expansion to include spaces is handled already - is that right?
â WEBjuju
Feb 8 at 15:55
and they'll want to quote the parameters in the iptables line as well
â Jeff Schaller
Feb 8 at 16:00
@WEBjuju, ah yes, I meant to write about that, edited why it works. And yes, you had the quotes in theiptables
command so there it works fine.
â ilkkachu
Feb 8 at 16:04
@ilkkachu gotcha, yes, it seems silly on my end. somehow i knew it subconsciously but couldn't bring forth the knowledge to a working solution. i have somehow muddled through without knowing this basic tenant until now, but i just seriously leveled up. much thanks!
â WEBjuju
Feb 8 at 16:14
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
accepted
Yep, that's a quoting issue: [ ! $3 ]
expands to [ ! south brisbane qld ]
(four arguments between [
and ]
). And when it sees four arguments, with the first one a !
, [
expects to see something like [ ! arg1 op arg2 ]
where op
is a binary operator. (this, again is one of the things different between [ .. ]
and [[ .. ]]
; see this Q and also this Q)
brisbane
isn't a valid operator, so it complains and returns 2, which is falsy so the statements inside the if
are not executed. To tell the difference between an error and a regular failing test, you'd need to explicitly test the return value against 2.
On the other hand, if $3
is empty, then the test becomes [ ! ]
, a one-argument test that checks if the only argument is nonempty (it is, it's the one-character string !
). In that case, it works as intended, though perhaps not for the reason you'd expect.
You want [ ! "$3" ]
or [ -z "$3" ]
to keep the string as one argument for [
.
Of course you could also invert the sense of the test, and do the actual work inside the if
, so that an error in the test would avoid running the main commands. But that would make the code structure a bit more unclear.
nice - so the reason it is working then is that even though it errors, $3 isn't empty so it passes the ! test and then i have it quoted in theiptables
command so its expansion to include spaces is handled already - is that right?
â WEBjuju
Feb 8 at 15:55
and they'll want to quote the parameters in the iptables line as well
â Jeff Schaller
Feb 8 at 16:00
@WEBjuju, ah yes, I meant to write about that, edited why it works. And yes, you had the quotes in theiptables
command so there it works fine.
â ilkkachu
Feb 8 at 16:04
@ilkkachu gotcha, yes, it seems silly on my end. somehow i knew it subconsciously but couldn't bring forth the knowledge to a working solution. i have somehow muddled through without knowing this basic tenant until now, but i just seriously leveled up. much thanks!
â WEBjuju
Feb 8 at 16:14
add a comment |Â
up vote
5
down vote
accepted
Yep, that's a quoting issue: [ ! $3 ]
expands to [ ! south brisbane qld ]
(four arguments between [
and ]
). And when it sees four arguments, with the first one a !
, [
expects to see something like [ ! arg1 op arg2 ]
where op
is a binary operator. (this, again is one of the things different between [ .. ]
and [[ .. ]]
; see this Q and also this Q)
brisbane
isn't a valid operator, so it complains and returns 2, which is falsy so the statements inside the if
are not executed. To tell the difference between an error and a regular failing test, you'd need to explicitly test the return value against 2.
On the other hand, if $3
is empty, then the test becomes [ ! ]
, a one-argument test that checks if the only argument is nonempty (it is, it's the one-character string !
). In that case, it works as intended, though perhaps not for the reason you'd expect.
You want [ ! "$3" ]
or [ -z "$3" ]
to keep the string as one argument for [
.
Of course you could also invert the sense of the test, and do the actual work inside the if
, so that an error in the test would avoid running the main commands. But that would make the code structure a bit more unclear.
nice - so the reason it is working then is that even though it errors, $3 isn't empty so it passes the ! test and then i have it quoted in theiptables
command so its expansion to include spaces is handled already - is that right?
â WEBjuju
Feb 8 at 15:55
and they'll want to quote the parameters in the iptables line as well
â Jeff Schaller
Feb 8 at 16:00
@WEBjuju, ah yes, I meant to write about that, edited why it works. And yes, you had the quotes in theiptables
command so there it works fine.
â ilkkachu
Feb 8 at 16:04
@ilkkachu gotcha, yes, it seems silly on my end. somehow i knew it subconsciously but couldn't bring forth the knowledge to a working solution. i have somehow muddled through without knowing this basic tenant until now, but i just seriously leveled up. much thanks!
â WEBjuju
Feb 8 at 16:14
add a comment |Â
up vote
5
down vote
accepted
up vote
5
down vote
accepted
Yep, that's a quoting issue: [ ! $3 ]
expands to [ ! south brisbane qld ]
(four arguments between [
and ]
). And when it sees four arguments, with the first one a !
, [
expects to see something like [ ! arg1 op arg2 ]
where op
is a binary operator. (this, again is one of the things different between [ .. ]
and [[ .. ]]
; see this Q and also this Q)
brisbane
isn't a valid operator, so it complains and returns 2, which is falsy so the statements inside the if
are not executed. To tell the difference between an error and a regular failing test, you'd need to explicitly test the return value against 2.
On the other hand, if $3
is empty, then the test becomes [ ! ]
, a one-argument test that checks if the only argument is nonempty (it is, it's the one-character string !
). In that case, it works as intended, though perhaps not for the reason you'd expect.
You want [ ! "$3" ]
or [ -z "$3" ]
to keep the string as one argument for [
.
Of course you could also invert the sense of the test, and do the actual work inside the if
, so that an error in the test would avoid running the main commands. But that would make the code structure a bit more unclear.
Yep, that's a quoting issue: [ ! $3 ]
expands to [ ! south brisbane qld ]
(four arguments between [
and ]
). And when it sees four arguments, with the first one a !
, [
expects to see something like [ ! arg1 op arg2 ]
where op
is a binary operator. (this, again is one of the things different between [ .. ]
and [[ .. ]]
; see this Q and also this Q)
brisbane
isn't a valid operator, so it complains and returns 2, which is falsy so the statements inside the if
are not executed. To tell the difference between an error and a regular failing test, you'd need to explicitly test the return value against 2.
On the other hand, if $3
is empty, then the test becomes [ ! ]
, a one-argument test that checks if the only argument is nonempty (it is, it's the one-character string !
). In that case, it works as intended, though perhaps not for the reason you'd expect.
You want [ ! "$3" ]
or [ -z "$3" ]
to keep the string as one argument for [
.
Of course you could also invert the sense of the test, and do the actual work inside the if
, so that an error in the test would avoid running the main commands. But that would make the code structure a bit more unclear.
edited Feb 8 at 16:06
answered Feb 8 at 15:54
ilkkachu
49.6k673137
49.6k673137
nice - so the reason it is working then is that even though it errors, $3 isn't empty so it passes the ! test and then i have it quoted in theiptables
command so its expansion to include spaces is handled already - is that right?
â WEBjuju
Feb 8 at 15:55
and they'll want to quote the parameters in the iptables line as well
â Jeff Schaller
Feb 8 at 16:00
@WEBjuju, ah yes, I meant to write about that, edited why it works. And yes, you had the quotes in theiptables
command so there it works fine.
â ilkkachu
Feb 8 at 16:04
@ilkkachu gotcha, yes, it seems silly on my end. somehow i knew it subconsciously but couldn't bring forth the knowledge to a working solution. i have somehow muddled through without knowing this basic tenant until now, but i just seriously leveled up. much thanks!
â WEBjuju
Feb 8 at 16:14
add a comment |Â
nice - so the reason it is working then is that even though it errors, $3 isn't empty so it passes the ! test and then i have it quoted in theiptables
command so its expansion to include spaces is handled already - is that right?
â WEBjuju
Feb 8 at 15:55
and they'll want to quote the parameters in the iptables line as well
â Jeff Schaller
Feb 8 at 16:00
@WEBjuju, ah yes, I meant to write about that, edited why it works. And yes, you had the quotes in theiptables
command so there it works fine.
â ilkkachu
Feb 8 at 16:04
@ilkkachu gotcha, yes, it seems silly on my end. somehow i knew it subconsciously but couldn't bring forth the knowledge to a working solution. i have somehow muddled through without knowing this basic tenant until now, but i just seriously leveled up. much thanks!
â WEBjuju
Feb 8 at 16:14
nice - so the reason it is working then is that even though it errors, $3 isn't empty so it passes the ! test and then i have it quoted in the
iptables
command so its expansion to include spaces is handled already - is that right?â WEBjuju
Feb 8 at 15:55
nice - so the reason it is working then is that even though it errors, $3 isn't empty so it passes the ! test and then i have it quoted in the
iptables
command so its expansion to include spaces is handled already - is that right?â WEBjuju
Feb 8 at 15:55
and they'll want to quote the parameters in the iptables line as well
â Jeff Schaller
Feb 8 at 16:00
and they'll want to quote the parameters in the iptables line as well
â Jeff Schaller
Feb 8 at 16:00
@WEBjuju, ah yes, I meant to write about that, edited why it works. And yes, you had the quotes in the
iptables
command so there it works fine.â ilkkachu
Feb 8 at 16:04
@WEBjuju, ah yes, I meant to write about that, edited why it works. And yes, you had the quotes in the
iptables
command so there it works fine.â ilkkachu
Feb 8 at 16:04
@ilkkachu gotcha, yes, it seems silly on my end. somehow i knew it subconsciously but couldn't bring forth the knowledge to a working solution. i have somehow muddled through without knowing this basic tenant until now, but i just seriously leveled up. much thanks!
â WEBjuju
Feb 8 at 16:14
@ilkkachu gotcha, yes, it seems silly on my end. somehow i knew it subconsciously but couldn't bring forth the knowledge to a working solution. i have somehow muddled through without knowing this basic tenant until now, but i just seriously leveled up. much thanks!
â WEBjuju
Feb 8 at 16:14
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f422842%2fbinary-operator-expected-quoting-question-for-shell-script-args%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
1
If your goal in testing
$3
is just to be sure that there are three parameters, then you can use the simpler$#
shell variable, which holds the number of parameters, eg.if [ $# -ne 3 ]
.â user1404316
Feb 8 at 17:45
@user1404316 very useful - thanks
â WEBjuju
Feb 8 at 21:10