I need to check if a string starts and ends with a single quote, for example 'My name is Mozart'
What I have is this, which doesn't work
if [[ $TEXT == '*' ]] ;
This does not work either
if [[ $TEXT == /'*/' ]] ;
But if I change it to
if [[ $TEXT == a*a ]] ;
it works for a sentence like 'an amazing apa'. So I Believe it has to do with the single quote sign.
Any ideas on how I can solve it?
$1 means an input argument and -z means non-defined or empty. You're testing whether an input argument to the script was defined when running the script. Follow this answer to receive notifications.
Introduction – In bash, we can check if a string begins with some value using regex comparison operator =~ .
Save this answer. Show activity on this post. $() means: "first evaluate this, and then evaluate the rest of the line". On the other hand ${} expands a variable.
$? is the exit status of the most recently-executed command; by convention, 0 means success and anything else indicates failure. That line is testing whether the grep command succeeded. The grep manpage states: The exit status is 0 if selected lines are found, and 1 if not found.
Cyrus' helpful answer solves your problem as posted.
However, I suspect you may be confused over quotes that are part of the shell syntax vs. quotes that are actually part of the string:
In a POSIX-like shell such as Bash, 'My name is Mozart'
is a single-quoted string whose content is the literal My name is Mozart
- without the enclosing '
. That is, the enclosing '
characters are a syntactic elements that tell the shell that everything between them is the literal contents of the string.
By contrast, to create a string whose content is actually enclosed in '
- i.e., has embedded '
instances, you'd have to use something like: "'My name is Mozart'"
. Now it is the enclosing "
instances that are the syntactic elements that bookend the string content.
"..."
string (double quotes) makes the contents subject to string interpolation (expansion of embedded variable references, arithmetic and command substitutions; none in the case at hand, however), so it's important to know when to use '...'
(literal strings) vs. "..."
(interpolated strings).'
instances in '...'
strings is actually not supported at all in POSIX-like shells, but in Bash, Ksh, and Zsh there's another string type that allows you to do that: ANSI C-quoted strings, $'...'
, in which you can embed '
escaped as \'
: $'\'My name is Mozart\''
"'"'My Name is Mozart'"'"
would also give you a string with contents 'My Name is Mozart'
.\
; therefore, \''My name is Mozart'\'
yields the same result.
The behavior of Bash's ==
operator inside [[ ... ]]
(conditionals) may have added to the confusion:
If the RHS (right-hand side - the operand to the right of operator ==
) is quoted, Bash treats it like a literal; only unquoted strings (or variable references) are treated as (glob-like) patterns:
'*'
matches literal *
, whereas *
(unquoted!) matches any sequence of characters, including none.
Thus:
[[ $TEXT == '*' ]]
would only ever match the single, literal character *
.
[[ $TEXT == /'*/' ]]
, because it mistakes /
for the escape character - which in reality is \
- would only match literal /*/
(/'*/'
is effectively a concatenation of unquoted /
and single-quoted literal */
).
[[ $TEXT == a*a ]]
, due to using an unquoted RHS, is the only variant that actually performs pattern matching: any string that starts with a
and ends with a
is matched, including aa
(because unquoted *
represents any sequence of characters).
To verify that Cyrus' commands do work with strings whose content is enclosed in (embedded) single quotes, try these commands, which - on Bash, Ksh, and Zsh - should both output yes
.
[[ "'ab'" == \'*\' ]] && echo yes # pattern matching, indiv. escaped ' chars.
[[ "'ab'" =~ ^\'.*\'$ ]] && echo yes # regex operator =~
With a regex:
if [[ $TEXT =~ ^\'.*\'$ ]]
With globbing:
if [[ $TEXT == \'*\' ]]
I am writing the complete bash script so you won't have any confusion:
#! /bin/bash
text1="'helo there"
if [[ $text1 =~ ^\'.*\'$ ]]; then
echo "text1 match"
else
echo "text1 not match"
fi
text2="'hello babe'"
if [[ $text2 =~ ^\'.*\'$ ]]; then
echo "text2 match"
else
echo "text2 not match"
fi
Save the above script as
matchCode.sh
Now run it as:
./matchCode
output:
text1 not match
text2 match
Ask if you have any confusion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With