Multiple -A with Greater Than/Less Than Break Bash Script

Multiple -a with greater than / less than break bash script

You cannot use < and > in bash scripts as such. Use -lt and -gt for that:

if [ $HOUR -gt 7 -a $HOUR -lt 17 ]

< and > are used by the shell to perform redirection of stdin or stdout.

The comparison that you say is working is actually creating a file named 7 in the current directory.

As for &&, that also has a special meaning for the shell and is used for creating an "AND list" of commands.

The best documentation for all these: man bash (and man test for details on comparison operators)

How to represent multiple conditions in a shell if statement?

Classic technique (escape metacharacters):

if [ \( "$g" -eq 1 -a "$c" = "123" \) -o \( "$g" -eq 2 -a "$c" = "456" \) ]
then echo abc
else echo efg
fi

I've enclosed the references to $g in double quotes; that's good practice, in general. Strictly, the parentheses aren't needed because the precedence of -a and -o makes it correct even without them.

Note that the -a and -o operators are part of the POSIX specification for test, aka [, mainly for backwards compatibility (since they were a part of test in 7th Edition UNIX, for example), but they are explicitly marked as 'obsolescent' by POSIX. Bash (see conditional expressions) seems to preempt the classic and POSIX meanings for -a and -o with its own alternative operators that take arguments.


With some care, you can use the more modern [[ operator, but be aware that the versions in Bash and Korn Shell (for example) need not be identical.

for g in 1 2 3
do
for c in 123 456 789
do
if [[ ( "$g" -eq 1 && "$c" = "123" ) || ( "$g" -eq 2 && "$c" = "456" ) ]]
then echo "g = $g; c = $c; true"
else echo "g = $g; c = $c; false"
fi
done
done

Example run, using Bash 3.2.57 on Mac OS X:

g = 1; c = 123; true
g = 1; c = 456; false
g = 1; c = 789; false
g = 2; c = 123; false
g = 2; c = 456; true
g = 2; c = 789; false
g = 3; c = 123; false
g = 3; c = 456; false
g = 3; c = 789; false

You don't need to quote the variables in [[ as you do with [ because it is not a separate command in the same way that [ is.


Isn't it a classic question?

I would have thought so. However, there is another alternative, namely:

if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ]
then echo abc
else echo efg
fi

Indeed, if you read the 'portable shell' guidelines for the autoconf tool or related packages, this notation — using '||' and '&&' — is what they recommend. I suppose you could even go so far as:

if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi

Where the actions are as trivial as echoing, this isn't bad. When the action block to be repeated is multiple lines, the repetition is too painful and one of the earlier versions is preferable — or you need to wrap the actions into a function that is invoked in the different then blocks.

How can I split a shell command over multiple lines when using an IF statement?

The line-continuation will fail if you have whitespace (spaces or tab characters¹) after the backslash and before the newline. With no such whitespace, your example works fine for me:

$ cat test.sh
if ! fab --fabfile=.deploy/fabfile.py \
--forward-agent \
--disable-known-hosts deploy:$target; then
echo failed
else
echo succeeded
fi

$ alias fab=true; . ./test.sh
succeeded
$ alias fab=false; . ./test.sh
failed

Some detail promoted from the comments: the line-continuation backslash in the shell is not really a special case; it is simply an instance of the general rule that a backslash "quotes" the immediately-following character, preventing any special treatment it would normally be subject to. In this case, the next character is a newline, and the special treatment being prevented is terminating the command. Normally, a quoted character winds up included literally in the command; a backslashed newline is instead deleted entirely. But otherwise, the mechanism is the same. Most importantly, the backslash only quotes the immediately-following character; if that character is a space or tab, you just get a literal space or tab; the backslash will have no effect on a subsequent newline.

¹ or carriage returns, for that matter, as Czechnology points out. The POSIX shell does not get along with Windows-formatted text files, not even in WSL. Or Cygwin, but at least their Bash port has added an igncr option that you can set -o to make it carriage-return-tolerant.

Awk greater than less than but within a set range

I think this awk should be enough for you:

awk '{print ($1 > 0 && $1 < $2)}'

About your requirement # 2:

Since any p cannot be negative as per requirement #1 therefore just checking $1 < $2 is enough for you.

How to split one string into multiple strings separated by at least one space in bash shell?

Did you try just passing the string variable to a for loop? Bash, for one, will split on whitespace automatically.

sentence="This is   a sentence."
for word in $sentence
do
echo $word
done

 

This
is
a
sentence.

Multiple if condition in bash not working

It's a difference between [ and [[. The first is a standard command, where = just tests for equality. (Note that the standard operator is =, not ==.) The latter is a feature from ksh, supported in Bash and Zsh, and there, =/== is a pattern match. Also, you should avoid using -a within [ .. ], it can break if you do something like [ "$a" = foo -a "$b" = bar ] and $a or $b contains a !.

So,

$ if [[ "crack" == "crack" && "something/play" == *"play"* ]]; then echo true; fi
true

See also (in unix.SE): Why is [ a shell builtin and [[ a shell keyword? and What is the difference between the Bash operators [[ vs [ vs ( vs ((?.

How to tell bash that the line continues on the next line

The character is a backslash \

From the bash manual:

The backslash character ‘\’ may be used to remove any special meaning
for the next character read and for line continuation.



Related Topics



Leave a reply



Submit