What does "$#" mean in bash? [duplicate] - linux

This question already has answers here:
What does the "$#" special parameter mean in Bash?
(2 answers)
Closed 8 years ago.
I have a script with this:
login {
# checking parameters -> if not ok print error and exit script
if [ $# -lt 2 ] || [ $1 == '' ] || [ $2 == '' ]; then
echo "Please check the needed options (username and password)"
echo ""
echo "For further Information see Section 13"
echo ""
echo "Press any key to exit"
read
exit
fi
} # /login
But I really dont know what the $# means on the third line.

The pound sign counts things.
If it's just $#, it's the number of positional parameters, like $1, $2, $3. (Not counting $0, mind you.)
If it's ${#var}, it's the number of characters in the expansion of the parameter. (String length)
If it's ${#var[#]}, it's the number of elements in the array. Since bash arrays are sparse, this can be different from the index of the last element plus one.

It's the number of arguments passed.
You can read it here, search for "Detecting command line arguments"

Related

Why am i getting an error near the if statement here? [duplicate]

This question already has answers here:
Why should there be spaces around '[' and ']' in Bash?
(5 answers)
Closed 8 months ago.
for i in {1..10}
if [ $i=5 ]
then
echo "Youve completed 5 iterations, do you wish to continue?"
read input
if [$input ="Yes"]
then
continue
else
break
fi
if [$i==10]
then
break
do
echo "Iteration no: $i"
echo "Enter a number"
read number
echo "youve entered $number"
done
It's helpful to review the basics of Bash Scripting a bit more before jumping into the fire.
if [ "foo" = "foo" ]
then
echo "Equal"
else
echo "Not Equal"
fi
In Bash script, the spacing between variables and brackets is significant, meaning the if statement above is NOT the same as [ "foo"=="foo"] (Notice the lack of a space)
Now let's add a loop
for i in {1..10}
do
if [ $i -eq 1 ]
then
echo "Equal"
else
echo "Not Equal"
fi
done
If you're comparing integers, you should use -eq for an equals comparison.
Make sure you're adding the 'do' and 'done' statements. It helps to use indents in your code to make it easier to follow the script execution. Everything 4 spaces over will execute inside the loop.
From here you should be able to build up to your final script which checks for user input.
It's fun to jump in and try new things but always be sure to reference the documentation! https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Commands

join bash remaining parameters from arg 3 onwards [duplicate]

This question already has answers here:
getting positional arguments in bash
(4 answers)
Closed 5 years ago.
I'd like to join and send the remaining parameters for a script to a command. Eg:
if [ "$2" == "exec" ]; then
other_script execute "$3 $4 $5 $6 $7 (etc etc etc)"
fi
Please advise.
One way is to use bash array slice notation:
foo() {
echo "[$1]"
echo "[$2]"
echo "[${#:3}]"
}
Produces:
$ foo a b c d ef
[a]
[b]
[c d ef]
Which you would implement in your code as:
if [ "$2" == "exec" ]; then
other_script execute "${#:3}"
fi
If you needed say the 3rd and 4th arguments, you could apply a length to the slice:
other_script execute "${#:3:2}" # :2 is a length specification
Another way, if you didn't need arguments $1 or $2 any longer, is to just shift them out of the way:
foo=${1:?Missing argument one}
bar=${2:-Default}
shift 2
echo "$#" # the first two args are gone, so this is now args #3 on
I prefer this way, honestly, for a couple of reasons:
Numbered args are hard to remember: named args are more clear.
The array slice notation isn't well-known (based on my experience), so it may cause some confusion with future maintenance.

Check if parameter is value X or value Y [duplicate]

This question already has answers here:
Bash If-statement to check If string is equal to one of several string literals [duplicate]
(2 answers)
Closed 6 years ago.
I want to check in my bash script, if a variable is equal to value 1 OR equal to value 2.
I don't want to use something like this, because the 'if true statements' are the same (some big echo texts), when the variable is equal to 1 or 2. I want to avoid data redundancy.
if [ $1 == 1 ] ; then echo number 1 ; else
if [ $1 == 2 ] ; then echo number 2 ; fi
More something like
if [ $1 == 1 OR 2 ] ; then echo number 1 or 2 ; fi
Since you are comparing integer values, use the bash arithmetic operator (()), as
(( $1 == 1 || $1 == 2 )) && echo "number 1 or 2"
For handling-strings using the regex operator in bash
test="dude"
if [[ "$test" =~ ^(dude|coolDude)$ ]]; then echo "Dude Anyway"; fi
# literally means match test against either of words separated by | as a whole
# and not allow for sub-string matches.
Probably the most easy to extend option is a case statement:
case $1 in
[12])
echo "number $1"
esac
The pattern [12] matches 1 or 2. For larger ranges you could use [1-5], or more complicated patterns like [1-9]|[1-9][0-9] to match any number from 1 to 99.
When you have multiple cases, you should separate each one with a ;;.

Why does [$value -lt 10] in shell result in command not found? [duplicate]

This question already has answers here:
"Command not found" when attempting integer equality in bash
(3 answers)
Closed 8 years ago.
Output 1:
Enter your value: 12
./testscript.sh: line 4: 12: command not found
Your value is more than 10
Output 2:
Enter your value: 5
./testscript.sh: line 4: 12: command not found
Your value is more than 10
I need to know what is wrong. My Linux test is just tomorrow:(
#!/bin/bash
echo -n "Enter your value: "
read value
if [$value -lt 10]
then
echo "Your value is less than 10"
else
echo "Your value is more than 10"
fi
your if statement should be as below. A space before ']' and space after '['
if [ $value -lt 10 ]
EDIT
As per the comments
you can always add optional ; at the end of the line. The below script would work fine.
a=20;
if [ $a -gt 10 ];
then
echo "true";
else
echo "false";
fi
you need to put your condition in the [ condition ]. The below one does not work.
( condition )
It would say command not found. As '(' is not command. where as '[' is a command in order to check a condition
And the more appropriate way is to use [[ ]] over [ ] when in Bash since you can avoid word splitting and pathname expansion with it. Other conditions can be added as well:
if [[ ! $value =~ [0-9]+ ]]; then
echo "Invalid input."
elif [[ value -lt 10 ]]; then
echo "Your value is less than 10."
elif [[ value -eq 10 ]]; then
echo "Your value is 10."
else
echo "Your value is more than 10."
fi
To throw yet another option into the mix: bash has (( ... )) -- arithmetic conditions:
if (( $value < 10 )); then ...
http://www.gnu.org/software/bash/manual/bashref.html#Conditional-Constructs
One thing you can do in bash with arithmetic expressions is to drop the $.
if (( value < 10 )); then
This is documented a bit obscurely in Shell arithmetic: "Within an expression, shell variables may also be referenced by name without using the parameter expansion syntax."
This may appeal to aficionados of C-like languages, but it's a bit out of step with the rest of the languages, and it doesn't apply to all variables (such as special paramaters ($#)
and array elements (${foo[3]})).

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