*I am having issue *
while comparing date variable in if clause, because i am getting one date variable value is "$'2014-04-19\r'" and another one is 2014-04-19.
how i come to know the value of variable is this
by set -x property in my shell script
value of variable in if condition has shown me in command line is below -
+ [ $'2014-04-19\r' == 2014-04-19 ]
so how can i compare because in simple text format both variable looks same, and i want to be true that condition.
can we remove $' and \r' from that variable...
You can compare using [[ and ]] in BASH like this:
s=$'2014-04-19\r'
[[ "$s" == '2014-04-19'? ]] && echo "similar"
OR more precisely:
[[ "$s" == '2014-04-19'$'\r' ]] && echo "similar"
you can use like :
sed 's/\'\\r\'//g' < your_input_file > your_output_file
It will replace the unwanted string with the space.
Related
This question already has answers here:
How to compare strings in Bash
(12 answers)
Closed 4 years ago.
I'm trying to get an if statement to work in Bash (using Ubuntu):
#!/bin/bash
s1="hi"
s2="hi"
if ["$s1" == "$s2"]
then
echo match
fi
I've tried various forms of the if statement, using [["$s1" == "$s2"]], with and without quotes, using =, == and -eq, but I still get the following error:
[hi: command not found
I've looked at various sites and tutorials and copied those, but it doesn't work - what am I doing wrong?
Eventually, I want to say if $s1 contains $s2, so how can I do that?
I did just work out the spaces bit... :/ How do I say contains?
I tried
if [[ "$s1" == "*$s2*" ]]
but it didn't work.
For string equality comparison, use:
if [[ "$s1" == "$s2" ]]
For string does NOT equal comparison, use:
if [[ "$s1" != "$s2" ]]
For the a contains b, use:
if [[ $s1 == *"$s2"* ]]
(and make sure to add spaces between the symbols):
Bad:
if [["$s1" == "$s2"]]
Good:
if [[ "$s1" == "$s2" ]]
You should be careful to leave a space between the sign of '[' and double quotes where the variable contains this:
if [ "$s1" == "$s2" ]; then
# ^ ^ ^ ^
echo match
fi
The ^s show the blank spaces you need to leave.
You need spaces:
if [ "$s1" == "$s2" ]
I suggest this one:
if [ "$a" = "$b" ]
Notice the white space between the openning/closing brackets and the variables and also the white spaces wrapping the '=' sign.
Also, be careful of your script header. It's not the same thing whether you use
#!/bin/bash
or
#!/bin/sh
Here's the source.
Bash 4+ examples. Note: not using quotes will cause issues when words contain spaces, etc. Always quote in Bash IMO.
Here are some examples Bash 4+:
Example 1, check for 'yes' in string (case insensitive):
if [[ "${str,,}" == *"yes"* ]] ;then
Example 2, check for 'yes' in string (case insensitive):
if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then
Example 3, check for 'yes' in string (case sensitive):
if [[ "${str}" == *"yes"* ]] ;then
Example 4, check for 'yes' in string (case sensitive):
if [[ "${str}" =~ "yes" ]] ;then
Example 5, exact match (case sensitive):
if [[ "${str}" == "yes" ]] ;then
Example 6, exact match (case insensitive):
if [[ "${str,,}" == "yes" ]] ;then
Example 7, exact match:
if [ "$a" = "$b" ] ;then
This question has already great answers, but here it appears that there is a slight confusion between using single equal (=) and double equals (==) in
if [ "$s1" == "$s2" ]
The main difference lies in which scripting language you are using. If you are using Bash then include #!/bin/bash in the starting of the script and save your script as filename.bash. To execute, use bash filename.bash - then you have to use ==.
If you are using sh then use #!/bin/sh and save your script as filename.sh. To execute use sh filename.sh - then you have to use single =. Avoid intermixing them.
I would suggest:
#!/bin/bash
s1="hi"
s2="hi"
if [ $s1 = $s2 ]
then
echo match
fi
Without the double quotes and with only one equals.
$ if [ "$s1" == "$s2" ]; then echo match; fi
match
$ test "s1" = "s2" ;echo match
match
$
I don't have access to a Linux box right now, but [ is actually a program (and a Bash builtin), so I think you have to put a space between [ and the first parameter.
Also note that the string equality operator seems to be a single =.
This is more a clarification than an answer! Yes, the clue is in the error message:
[hi: command not found
which shows you that your "hi" has been concatenated to the "[".
Unlike in more traditional programming languages, in Bash, "[" is a command just like the more obvious "ls", etc. - it's not treated specially just because it's a symbol, hence the "[" and the (substituted) "$s1" which are immediately next to each other in your question, are joined (as is correct for Bash), and it then tries to find a command in that position: [hi - which is unknown to Bash.
In C and some other languages, the "[" would be seen as a different "character class" and would be disjoint from the following "hi".
Hence you require a space after the opening "[".
Use:
#!/bin/bash
s1="hi"
s2="hi"
if [ "x$s1" == "x$s2" ]
then
echo match
fi
Adding an additional string inside makes it more safe.
You could also use another notation for single-line commands:
[ "x$s1" == "x$s2" ] && echo match
For a version with pure Bash and without test, but really ugly, try:
if ( exit "${s1/*$s2*/0}" )2>/dev/null
then
echo match
fi
Explanation: In ( )an extra subshell is opened. It exits with 0 if there was a match, and it tries to exit with $s1 if there was no match which raises an error (ugly). This error is directed to /dev/null.
I have a string: dev/2.0 or dev/2.0-tymlez. How can I extract the string after the last - hyphen in bash? If there is no -, then the variable should be empty else tymlez and I want to store the result in $STRING. After that I would like to check the variable with:
if [ -z "$STRING" ]
then
echo "\$STRING is empty"
else
echo "\$STRING is NOT empty"
fi
Is that possible?
I recommend against calling your variable STRING. All-uppercase variables are used by the system (e.g. HOME) or the shell itself (e.g. PWD, RANDOM).
That said, you could do something like
string='dev/2.0-tymlez'
case "$string" in
*-*) string="${string##*-}";;
*) string='';;
esac
It's a bit clunky: It first checks whether there are any - at all, and if so, it removes the longest prefix matching *-; otherwise it just sets string to empty (because *- wouldn't have matched anything then).
You could use the =~ operator:
string="dev/2.0-tymlez"
[[ $string =~ -([^-]+)$ ]]; string=${BASH_REMATCH[1]}
BASH_REMATCH is a special array where the matches from [[ ... =~ ... ]] are assigned to.
You can use sed:
for string in "dev/2.0" "dev/2.0-1-2-3" "dev/2.0-tymlez"; do
string=$(sed 's/[^-]*[-]*//' <<< "${string}")
echo "string=[${string}]"
done
Result
string=[]
string=[1-2-3]
string=[tymlez]
If tag_len is greater than 18 or tag_len is 19 and the tag is not ends with "A",
I want to cut the tag to length 18.
I tried several options but that is not working correctly.
Could you let me now how I can do this?
#officail daily release TAG check
official_tag_len=18
export tag_len=`expr length $TAG`
if (($tag_len > $official_tag_len))
then
echo "$TAG length is greater than $official_tag_len"
if (($tag_len == ($official_tag_len+1))) && (($TAG == *A))
then
echo $TAG is an AM daily tag
else
echo $TAG is a temporary tag. reset to daily tag
export TAG=$($TAG:0:$official_tag_len)
fi
fi
UPDATE
the final error message is
e7e10_preqe2:0:18: command not found
I edit the code "export TAG=$($TAG:0:$official_tag_len)"
referring to Extract substring in Bash
and one more thing,
at first I wrote [[ instead of (( in if condition but command not found error occurs in [[ line.
Usually, I used [ ] expression in if condition.
Are there any exceptional cases?
The question setup is a bit difficult to understand, but I think this runs the way you want on bash. You didn't specify interpreter for the question..
I have taken liberty to take the "TAG" as input parameter (TAG=$1, and calculate it's length using command wc).
I have replaced all the if statements to use square brackets, and also use keyword -gt (greater than) for comparison (use lt for <, and eq for ==). These are meant to be used for numerical comparison.
#!/bin/bash
#officail daily release TAG check
TAG=$1
tag_len=`echo $TAG | wc -c`
official_tag_len=18
echo "input $tag, length: $tag_len"
if [[ $tag_len -gt $official_tag_len ]];
then
echo "$TAG length is greater than $official_tag_len"
if [[ $tag_len -eq $(($official_tag_len+1)) ]] && [[ $TAG == *A ]];
then
echo $TAG is an AM daily tag
else
echo $TAG is a temporary tag. reset to daily tag
export TAG=${TAG:0:official_tag_len}
echo "new tag: [$TAG]"
fi
fi
Looking at other Bash scripts, I see people comparing variables like: $S == $T while at other times I see the variable being wrapped inside strings: "$S" == "$T".
Some experiments seem to suggest that both do the same. The demo below will print equal in both cases (tested with GNU bash, version 4.2.37):
#!/usr/bin/env bash
S="text"
T="text"
if [[ $S == $T ]]; then
echo "equal"
fi
if [[ "$S" == "$T" ]]; then
echo "equal"
fi
My question: if there's a difference between $S == $T and "$S" == "$T", what is it?
If you use [[ they are almost the same, but not quite...
When the == and != operators are used, the string to the right of the operator is
considered a pattern and matched according to the rules described below under Pattern
Matching. [...]
Any part of the pattern may be quoted to force it to be matched as a string.
If you use [ then you have to use quotes unless you know that the variables cannot be empty or contain whitespace.
Just to be on the safe side, you probably want to quote all your variables all the time.
Before I ran the script I have entered
# export CPIC_MAX_CONV=500
The following is the test1.script file
#!/bin/bash
function cpic () {
var="`export | grep -i "CPIC_MAX_CONV" | awk '/CPIC_MAX_CONV/ { print $NF } '`"
[[ $var=="" ]] && (echo "Empty String <<")
[[ $var!="" ]] && (echo "$CPIC_MAX_CONV")
echo "$var" ;
}
cpic
The output is:
# test1.script ---- Me running the file
Empty String <<
500
CPIC_MAX_CONV="500"
No matter what I use "" or '' or [ or [[ the result is the same. The CPIC_MAX_CONV variable is found by the above script.
I am running this on Linux/CentOS 6.3.
The idea is simple: To find if CPIC_MAX_CONV is defined in the environment and return the value of it. If an empty space is there then of course the variable is not present in the system.
Why do you always get true? Let's play a little bit in your terminal first:
$ [[ hello ]] && echo "True"
What do you think the output is? (try it!) And with the following?
$ [[ "" ]] && echo "True"
(try it!).
All right, so it seems that a non-empty string is equivalent to the true expression, and an empty string (or an unset variable) is equivalent to the false expression.
What you did is the following:
[[ $var=="" ]]
and
[[ $var!="" ]]
so you gave a non-empty string, which is true!
In order to perform the test, you actually need spaces between the tokens:
[[ $var == "" ]]
instead. Now, your test would be better written as:
if [[ -z "$var" ]]; then
echo "Empty String <<"
else
echo "$CPIC_MAX_CONV"
fi
(without the sub-shells, and with just one test).
There's more to say about your scripting style. With no offence, I would say it's really bad:
Don't use backticks! Use the $(...) construct instead. Hence:
var="$(export | grep -i "CPIC_MAX_CONV" | awk '/CPIC_MAX_CONV/ { print $NF } ')"
Don't use function blah to define a function. Your function should have been defined as:
cpic () {
local var="$(export | grep -i "CPIC_MAX_CONV" | awk '/CPIC_MAX_CONV/ { print $NF } ')"
if [[ -z "$var" ]]; then
echo "Empty String <<"
else
echo "$CPIC_MAX_CONV"
fi
}
Oh, I used the local keyword, because I guess you're not going to use the variable var outside of the function cpic.
Now, what's the purpose of the function cpic and in particular of the stuff where you're defining the variable var? It would be hard to describe (as there are so many cases you haven't thought of). (Btw, your grep seems really useless here). Here are a few cases you overlooked:
An exported variable is named somethingfunnyCPIC_MAX_CONVsomethingevenfunnier
An exported variable contains the string CPIC_MAX_CONV somewhere, e.g.,
export a_cool_variable="I want to screw up Randhawa's script and just for that, let's write CPIC_MAX_CONV somewhere here"
Ok, I don't want to describe what your line is doing exactly, but I kind of guess that your purpose is to know whether the variable CPIC_MAX_CONV is set and marked for export, right? In that case, you'd be better with just this:
cpic () {
if declare -x | grep -q '^declare -x CPIC_MAX_CONV='; then
echo "Empty String <<"
else
echo "$CPIC_MAX_CONV"
fi
}
It will be more efficient, and much more robust.
Oh, I'm now just reading the end of your post. If you want to just tell if variable CPIC_MAX_CONV is set (to some non-empty value — it seems you don't care if it's marked for export or not, correct me if I'm wrong), it's even simpler (and it will be much much more efficient):
cpic () {
if [[ "$CPIC_MAX_CONV" ]]; then
echo "Empty String <<"
else
echo "$CPIC_MAX_CONV"
fi
}
will do as well!
Do you really care whether CPIC_MAX_CONV is an environment variable versus just 'it is a variable that might be an environment variable'? Most likely, you won't, not least because if it is a variable but not an environment variable, any script you run won't see the value (but if you insist on using aliases and functions, then it might matter, but still probably won't).
It appears, then, that you are trying to test whether CPIC_MAX_CONV is set to a non-empty value. There are multiple easy ways to do that — and then there's the way you've tried.
: ${CPIC_MAX_CONV:=500}
This ensures that CPIC_MAX_CONV is set to a non-empty value; it uses 500 if there previously wasn't a value set. The : (colon) command evaluates its arguments and reports success. You can arrange to export the variable after it is created if you want to with export CPIC_MAX_CONV.
If you must have the variable set (there is no suitable default), then you use:
: ${CPIC_MAX_CONV:?}
or
: ${CPIC_MAX_CONV:?'The CPIC_MAX_CONV variable is not set but must be set'}
The difference is that you can use the default message ('CPIC_MAX_CONV: parameter null or not set') or specify your own.
If you're only going to use the value once, you can do an 'on the fly' substitution in a command with:
cpic_command -c ${CPIC_MAX_CONV:-500} ...
This does not create the variable if it does not exist, unlike the := notation which does.
In all these notations, I've been using a colon as part of the operation. That enforces 'null or not set'; you can omit the colon, but that allows an empty string as a valid value, which is probably not what you want. Note that a string consisting of just a blank is 'not empty'; if you need to validate that you've got a non-empty string, you have to work a little harder.
I'm not dissecting your misuse of the [[ command; gniourf_gniourf has provided an excellent deconstruction of that, but overlooked the simpler notations available to do what seems to be the job.
Try this:
#!/bin/bash
function cpic () {
var="`export | grep -i "CPIC_MAX_CONV"`"
[ "$var" = "" ] && (echo "Empty String <<")
[ "$var" != "" ] && echo "$CPIC_MAX_CONV"
}
cpic
You need spaces in your conditions.
#!/bin/bash
function cpic () {
var="`export | grep -i "CPIC_MAX_CONV" | awk '/CPIC_MAX_CONV/ { print $NF } '`"
[[ $var == "" ]] && (echo "Empty String <<")
[[ $var != "" ]] && (echo "$CPIC_MAX_CONV")
echo "$var" ;
}
cpic