I want to concatenate string and int. But it doesn't work with & and add operator.
echo "abc" & 2
But it doesn't work.
There's an operator $ that converts something to string.
echo "abc" & $2
echo "abc", 2 # echo automatically applies `$` to its arguments
Related
I was trying to check if an array contained a value and I found Check if a Bash array contains a value
It did not work for me, and it was because I decided to remove the spaces surrounding the quotes, like this:
words=(aa bb cc)
[[ " ${words[#]} " =~ " a " ]] && echo "YES" || echo "NO"; # This is the real answer, and it works
------
[[ "${words[#]}" =~ "a" ]] && echo "YES" || echo "NO"; # This does not work. Why???
Whats the difference when you surround them with spaces or when you dont?
And for my curiosity. In the previous question I mentioned, some answers/comments go with:
${array[*]}, and others with ${array[#]}
Do they both "iterate" through the loop in the same way?
[[ string =~ regex ]] checks if regex matches any substring of string. That operator does not iterate over your array entries as for entry in "${words[#]}" would do. It cannot even handle arrays.
[[ " ${words[#]} " =~ " a " ]] is only a hack for finding array elements. The array is converted into a single string where all array entries are surrounded by spaces. Then, we search for an element using a string search. This only works reliably, if the array entries themselves do not contain any spaces.
For the difference between ${array[*]} and ${array[#]} see bash's manual:
If the word is double-quoted, ${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS variable [= a space by default], and ${name[#]} expands each element of name to a separate word.
So in this case, * would be the logical way to write [[ " ${words[*]} " =~ " a " ]], because it is equivalent to [[ " aa bb cc " =~ " a " ]].
That # works here too is somewhat strange, because [[ " aa" "bb" "cc " =~ " a " ]] gives a syntax error. Bash tolerating the misused # in [[ is probably an undocumented "feature" related to the (documented) disabled word-splitting inside [[. For the basic POSIX test command [ the difference between * and # works as expected, meaning a=("x" "=" "y"); [ "${a[#]}" ] fails because x != y.
`read -p "Enter first string: " VAR1`
`read -p "Enter second string: " VAR2`
`echo "You entered $VAR1"`
`echo "You entered $VAR2"`
`function display()`
`{`
`a=$1`
`b=$2`
if [ '$a' == '$b' ]; then
echo "Strings are equal"
else
echo "Strings are not equal"
fi
`}`
`display VAR1 VAR2`
Function is not giving desired output, it always returns "Strings are not equal"
the [ takes = sign as comparison operator, not the ==. Please use =.
the quoting '' does not allow the shell to resolve the $, please use "" quotes instead.
a=x b=x
If [ $a -eq $b ]
Then
echo "a is equal to b"
else
echo "a is not equal to b"
fi
Will the above code successfully output "a is equal to b" or there is some error?
When looking at your script, you use the single bracket version of the test command. This is in contrast to the double-bracket version which is a shell-internal test.
The test command states:
INTEGER1 -eq INTEGER2 : INTEGER1 is equal to INTEGER2
But you are not comparing integers, but strings (unless x could be a dummy name for something that could be an integer.). Hence, the test will fail.
$ [ x -eq x ]
[: integer expression expected: x
So your output will read a is not equal to b.
If you want to compare strings, then it is advised to use the operator =:
STRING1 = STRING2 : the strings are equal
-eq is for integer comparisons, but you are comparing strings. Use = (or bash-ism ==):
[ "$a" = "$b" ]
Like i did, quote variable expansions to prevent word splitting and pathname expansion.
I am writing a script that reads input of color hex-code from user, i.e
#ffffff
I also need to check length of that string to be equal to 7 (1 hash symbol + 6 digits) and have "#" symbol as 1st character. Here's my code:
read color
until [ ${#color} -ge 7 ] && [ ${color:0:1} -eq "#" ]
do
echo "Color code must be 7 characters long and start with '#'!"
read color
done
But when I try to, I get an error
[: #: integer expression expected
It works perfect if string is not starting with hash.
Is there a way to make it work?
You are trying to do a numeric comparison -eq, instead of a string comparison:
${color:0:1} -eq "#"
should be
"${color:0:1}" = "#"
instead.
INTEGER1 -eq INTEGER2 - INTEGER1 is equal to INTEGER2
STRING1 = STRING2 - the strings are equal
(man test)
If you only need this to work in bash, use regular expression matching:
color=
until [[ $color =~ ^\#[[:xdigit:]]{6}$ ]]; do
IFS= read -r color
done
For any POSIX shell, use a case statement to allow pattern matching
color=
until :; do
IFS= read -r color
case $color in
\#[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]) break ;;
esac
done
or use the expr command:
color=
until IFS= read -r color && expr "$color" : "#[[:xdigit:]]\{6\}$"; do
:
done
Bash scripts use = for string comparison, so your code should be:
read color
until [ ${#color} -ge 7 ] && [ ${color:0:1} = "#" ]
do
echo "Color code must be 7 characters long and start with '#'!"
read color
done
It's saying integer expression expected because -eq is for integer comparisons
I am asking user to enter 2 numbers and s for sum, or "p" for product.
when I run the script I don't see any results
here is my script
#!/bin/bash
read -p "please enter two integers, s or p to calculate sum or product of this numbers: " num1 num2 result
if [ result == "s" ]
then
echo "num1+num2" | bc
elif [ result == "p" ]
then
echo $((num1*num2))
fi
You are comparing the string result, not the value of the variable result.
if [ "$result" = s ]; then
echo "$(($num1 + $num2))"
elif [ "$result" = p ]; then
echo "$(($num1 * $num2))"
fi
Inside $((...)), you can omit the leading $ because a string is assumed to be a variable name to be dereferenced.
There's no reason to use bc if you intend to restrict the inputs to integers.
To complement chepner's helpful answer, which explains the problem with the code in the question well, with a solution inspired by DRY[1]
:
# Prompt the user.
prompt='please enter two integers, s or p to calculate sum or product of this numbers: '
read -p "$prompt" num1 num2 opChar
# Map the operator char. onto an operator symbol.
# In Bash v4+, consider using an associative array for this mapping.
case $opChar in
'p')
opSymbol='*'
;;
's')
opSymbol='+'
;;
*)
echo "Unknown operator char: $opChar" >&2; exit 1
;;
esac
# Perform the calculation.
# Note how the variable containing the *operator* symbol
# *must* be $-prefixed - unlike the *operand* variables.
echo $(( num1 $opSymbol num2 ))
[1] Except for read's -p option, the solution is POSIX-compliant; it does, however, also work in dash, which is mostly a POSIX-features-only shell.