Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shell script Bash, Check if string starts and ends with single quotes

Tags:

bash

shell

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?

like image 388
chichi Avatar asked Oct 29 '16 09:10

chichi


People also ask

What does [- Z $1 mean in bash?

$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.

How do you check if a string starts with a character in bash?

Introduction – In bash, we can check if a string begins with some value using regex comparison operator =~ .

What's do `` $() ${} commands do in bash?

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.

What is $? == 0 in shell script?

$? 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.


3 Answers

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.

    • Note, however, that using a "..." 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).
    • Embedding ' 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\''
    • Another option is to use string concatenation: In POSIX-like shells, you can place substrings employing different quoting styles (including unquoted tokens) directly next to one another in order to form a single string: "'"'My Name is Mozart'"'" would also give you a string with contents 'My Name is Mozart'.
      POSIX-like shells also allow you to escape individual, unquoted characters (meaning: neither part of a single- nor a double-quoted string) with \; 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 =~
like image 150
mklement0 Avatar answered Nov 10 '22 19:11

mklement0


With a regex:

if [[ $TEXT =~ ^\'.*\'$ ]]

With globbing:

if [[ $TEXT == \'*\' ]]
like image 26
Cyrus Avatar answered Nov 10 '22 20:11

Cyrus


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.

like image 12
Sulav Timsina Avatar answered Nov 10 '22 20:11

Sulav Timsina