Error using test command in if statement - linux

I am trying to create an if statement using the test command that checks if the variable "name" contains "Scott Pearce".
#!/bin/bash
name="Scott Pearce"
if test $name == "Scott Pearce";
then
echo "Yes"
else
echo "No"
fi
When I run the script I get an error saying :
./script1: line 5: test: too many arguments
Any idea what I am doing wrong?

if test "$name" = "Scott Pearce";
You need to quote the variable, otherwise when the shell expands it, test will not get the right number of arguments since your variable contains a space.
Also the string equality operator for test is =, not ==.

If you really want to test contains, then pick one of
bash
if [[ $name == *"Scott Pearce"* ]]; then ...
POSIX
case "$name" in
*"Scott Pearce"*) echo Hi Scott ;;
*) echo Begone stranger ;;
esac
The == operator in bash's [[ command is a pattern matching operator.

Related

Read command in if clause in bash

elif [ "$arg" == "--file" ] || [ "$arg" == "-f" ] && [[ read var ]]
then
touch $var
I'm writing a bash script which takes in a command-line input, either long-form or short-form along with the file name to create an empty file with touch command. the above snippet is what I tried to do, but there's an error unary "read: unary operator expected".please help
This happens for most commands:
$ [[ echo "hello world" ]]
bash: conditional binary operator expected
bash: syntax error near `world"'
This is because [[ .. ]] should be used to compare values, and not to run commands. To run a command, don't wrap it in anything:
$ echo "hello world"
hello world
Applied to your example:
echo "You are expected to type in a value, but you will receive no prompt."
arg="-f"
if [ "$arg" == "--file" ] || [ "$arg" == "-f" ] && read var
then
echo "You entered: $var"
fi
Bash needs to know that it's running a whole command
To make bash aware that it's running a command you can use the backtick syntax (not recommended) or the preferred $() command substitution syntax. Without this syntax, bash is assuming that you're putting two separate strings inside of that condition.
The error you're getting is saying that you are trying to compare two strings without an operator to do so (i.e. -eq or ==).
Here is an example of how to make it recognize your commands:
elif [[ ... ]] && [[ $(read var) ]]
then
However, this won't work. This will evaluate to false. This is because you haven't printed anything out and as such an empty string ("") is falsey.
echo your variable to test its value
elif [[ ... ]] && [[ $(read var; echo $var) ]]
then
This will read into the variable and then test if the user has typed anything into it. If the user doesn't type anything, it will evaluate to false, otherwise, it will evaluate to true and run the body of the elif statement.

Unexpected output for bash argument equality check [duplicate]

This question already has answers here:
How to compare strings in Bash
(12 answers)
Closed 3 years ago.
I have a basic string equality check in a Bash script, but the output is not as expected.
To reproduce, copy the code below into an executable file (called 'deploy' in my examples below).
#!/bin/bash
echo $1
if [[ "$1" -eq "--help" ]] || [[ "$1" -eq "-h" ]]; then
echo "hello"
fi
If I run the script like so:
./deploy -h
The output is:
-h
hello
If I run the script like so:
./deploy --help
The output is:
-help
Why does the conditional statement not resolve to true?
-eq compares integers. Use == or = to compare strings.
if [[ "$1" == "--help" ]] || [[ "$1" == "-h" ]]; then
echo "hello"
fi
You could omit the quotes. Variable expansions on the left-hand side of == are safe when using double brackets.
You can also use || inside the brackets. It's not possible to do that with single brackets, but double brackets are a syntactical feature with special parsing rules that allow it.
if [[ $1 == --help || $1 == -h ]]; then
echo "hello"
fi
If it gets more complicated you might also consider a case block.
case $1 in
-h|--help)
echo "hello";;
esac
If -eq is for numerical comparison, how come ./deploy -h worked as expected?
Arithmetic evaluation normally prints an error message when given illegal expressions, but as it happens the two strings you're asking it to evaluate are syntactically valid.
-h negates the value of the undefined variable $h. The result is 0.
--help is decrements the undefined variable $help. The result is -1.
Try an invalid string and you'll get an error.
$ ./deploy 'foo bar'
bash: [[: foo bar: syntax error in expression (error token is "bar")
$ ./deploy #
bash: [[: #: syntax error in expression (error token is "#")

reading a variable and searching if and then statement to match something in a variable

Hi I Have a command/function is a script that assigns users names to variable
so:
var1=dedwards torontobgs NJVMTTS2 srounce jstickler
echo $var1 produces >> dedwards torontobgs NJVMTTS2 srounce jstickler
How can I write a command to see if the userid "NJVMTTS2" exist in the variable ? It seems that variable is treated as one string and not individual string?
I know this is simple but cannot get it to work
What I want to do is as follow:
if $1 ( passed by anther function ) exist in $VAR1
then do something
so if $1 = NJVMTTS2
and if NJVMTTS2 contained in the $VAR1
Then do echo "yes" else echo "no"
Just standard pattern matching.
var1='dedwards torontobgs NJVMTTS2 srounce jstickler'
if [[ $var1 = *NJVMTTS2* ]]; then
…
fi
Or, for portability:
case "$var1" in
*NJVMTTS2*) …;;
esac
Update
if NJVMTTS2 is in a parameter, you should quote the parameter expansion, but you must be careful not to quote the pattern:
case "$var1" in
*"$1"*) …;;
esac
First, your assignment should be quoted, otherwise var1 will contain only the first word.
var1="dedwards torontobgs NJVMTTS2 srounce jstickler"
Then you can grep for the name inside the variable:
if echo $var1 | grep '\bNJVMTTS2\b' >/dev/null; then echo Found it; fi
The \b word boundary symbols make sure you look for the whole word, thus matching NJVMTTS2 but not fooNJVMTTS2bar
If fooNJVMTTS2bar is also OK, the other answer will work. #Kojiro's solution also has the advantage that it does not use an external program, it's pure shell.

Bash ARGS help - getting random error

Trying to set rules if a certain variable is put into place, can someone identify wtf I'm missing here?
test.sh:
#!/bin/bash
args=($#)
if [ "$#" = "--cron" ]; then
echo "WORKS!";
else echo "FAILS"
fi
output of ./test.sh:
./test.sh: line 3: [: =: unary operator expected
FAILS
However, when I run ./test.sh --cron, it works, and WORKS is output.
The correct way to do this varies a bit depending on exactly what you're trying to do. If you want to check whether the first argument is --cron, use this:
if [ "$1" = "--cron" ]; then
If you want to check whether the only argument is --cron, use this:
if [ "$*" = "--cron" ]; then
(Note that this is one of very few cases where "$*" is the right way to do something -- it expands to all arguments separated by spaces, but treated as a single word for parsing purposes.)
If you want to check whether any argument is --cron, use this:
cronopt=false
for argument; do
if [ "$argument" = "--cron" ]; then
cronopt=true
break # note: if you are scanning the arguments for other things too, remove this
fi
done
if $cronopt; then
...
BTW, I'm not sure what you're using the args=($#) line for, but if you want to store the arguments in an array the correct way to do it is args=("$#") -- the quotes keep it from doing word splitting, filename expansion, etc before putting the args into the array.
This should work, but only for the first element, of you want more you might have to do a for or while loop to iterate thru the arguments.
#!/bin/bash
args=($1)
if [ $args ] && [ $args = "--cron" ]; then
echo "WORKS!";
else echo "FAILS"
fi
In this case, I believe "$#" is too well quoted.
Try comparing against "$1", or use:
#!/bin/bash
args=($#)
if [ "$*" = "--cron" ]; then
echo "WORKS!";
else
echo "FAILS"
fi

How to detect spaces in shell script variable [duplicate]

This question already has answers here:
How to check if a string has spaces in Bash shell
(10 answers)
Closed 3 years ago.
e.g string = "test test test"
I want after finding any occurance of space in string, it should echo error and exit else process.
The case statement is useful in these kind of cases:
case "$string" in
*[[:space:]]*)
echo "argument contains a space" >&2
exit 1
;;
esac
Handles leading/trailing spaces.
There is more than one way to do that; using parameter expansion
you could write something like:
if [ "$string" != "${string% *}" ]; then
echo "$string contains one or more spaces";
fi
For a purely Bash solution:
function assertNoSpaces {
if [[ "$1" != "${1/ /}" ]]
then
echo "YOUR ERROR MESSAGE" >&2
exit 1
fi
}
string1="askdjhaaskldjasd"
string2="asjkld askldja skd"
assertNoSpaces "$string1"
assertNoSpaces "$string2" # will trigger error
"${1/ /}" removes any spaces in the input string, and when compared to the original string should be exactly the same if there are not spaces.
Note the quotes around "${1/ /}" - This ensures that leading/trailing spaces are taken into consideration.
To match more than one character, you can use regular expressions to define a pattern to match - "${1/[ \\.]/}".
update
A better approach would be to use in-process expression matching. It will probably be a wee bit faster as no string manipulation is done.
function assertNoSpaces {
if [[ "$1" =~ '[\. ]' ]]
then
echo "YOUR ERROR MESSAGE" >&2
exit 1
fi
}
For more details on the =~ operator, see the this page and this chapter in the Advanced Bash Scripting guide.
The operator was introduced in Bash version 3 so watch out if you're using an older version of Bash.
update 2
Regarding question in comments:
how to handle the code if user enter
like "asd\" means in double quotes
...can we handle it??
The function given above should work with any string so it would be down to how you get input from your user.
Assuming you're using the read command to get user input, one thing you need to watch out for is that by default backslash is treated as an escape character so it will not behave as you might expect. e.g.
read str # user enters "abc\"
echo $str # prints out "abc", not "abc\"
assertNoSpaces "$str" # no error since backslash not in variable
To counter this, use the -r option to treat backslash as a standard character. See read MAN Page for details.
read -r str # user enters "abc\"
echo $str # prints out "abc\"
assertNoSpaces "$str" # triggers error
The == operator inside double brackets can match wildcards.
if [[ $string == *' '* ]]
You can use grep as:
string="test test test"
if ( echo "$string" | grep -q ' ' ); then
echo 'var has space'
exit 1
fi
I just ran into a very similar problem while handling paths. I chose to rely on my shell's parameter expansion rather than looking for a space specifically. It does not detect spaces at the front or the end, though.
function space_exit {
if [ $# -gt 1 ]
then
echo "I cannot handle spaces." 2>&1
exit 1
fi
}

Resources