English 中文(简体)
Case insensitive comparison of strings in shell script
原标题:

The == operator is used to compare two strings in shell script. However, I want to compare two strings ignoring case, how can it be done? Is there any standard command for this?

最佳回答

if you have bash

str1="MATCH"
str2="match"
shopt -s nocasematch
case "$str1" in
 $str2 ) echo "match";;
 *) echo "no match";;
esac

otherwise, you should tell us what shell you are using.

alternative, using awk

str1="MATCH"
str2="match"
awk -vs1="$str1" -vs2="$str2"  BEGIN {
  if ( tolower(s1) == tolower(s2) ){
    print "match"
  }
} 
问题回答

In Bash, you can use parameter expansion to modify a string to all lower-/upper-case:

var1=TesT
var2=tEst

echo ${var1,,} ${var2,,}
echo ${var1^^} ${var2^^}

All of these answers ignore the easiest and quickest way to do this (as long as you have Bash 4):

if [ "${var1,,}" = "${var2,,}" ]; then
  echo ":)"
fi

All you re doing there is converting both strings to lowercase and comparing the results.

Save the state of nocasematch (in case some other function is depending on it being disabled):

local orig_nocasematch=$(shopt -p nocasematch; true)
shopt -s nocasematch

[[ "foo" == "Foo" ]] && echo "match" || echo "notmatch"

$orig_nocasematch

Note that local is only required inside a function.
Also, the ; true part will prevent the shell from exiting when set -e is on and $(shopt -p nocasematch) fails (because nocasematch was NOT set at all).

One way would be to convert both strings to upper or lower:

test $(echo "string" | /bin/tr  [:upper:]   [:lower:] ) = $(echo "String" | /bin/tr  [:upper:]   [:lower:] ) && echo same || echo different

Another way would be to use grep:

echo "string" | grep -qi  ^String$  && echo same || echo different

I came across this great blog/tutorial/whatever about dealing with case sensitive pattern. The following three methods are explained in details with examples:

1. Convert pattern to lowercase using tr command

opt=$( tr  [:upper:]   [:lower:]  <<<"$1" )
case $opt in
        sql)
                echo "Running mysql backup using mysqldump tool..."
                ;;
        sync)
                echo "Running backup using rsync tool..."
                ;;
        tar)
                echo "Running tape backup using tar tool..."
                ;;
        *)
                echo "Other options"
                ;;
esac

2. Use careful globbing with case patterns

opt=$1
case $opt in
        [Ss][Qq][Ll])
                echo "Running mysql backup using mysqldump tool..."
                ;;
        [Ss][Yy][Nn][Cc])
                echo "Running backup using rsync tool..."
                ;;
        [Tt][Aa][Rr])
                echo "Running tape backup using tar tool..."
                ;;
        *)
                echo "Other option"
                ;;
esac

3. Turn on nocasematch

opt=$1
shopt -s nocasematch
case $opt in
        sql)
                echo "Running mysql backup using mysqldump tool..."
                ;;
        sync)
                echo "Running backup using rsync tool..."
                ;;
        tar)
                echo "Running tape backup using tar tool..."
                ;;
        *)
                echo "Other option"
                ;;
esac

shopt -u nocasematch

For zsh the syntax is slightly different, but still shorter than most answers here:

> str1= mAtCh 
> str2= MaTcH 
> [[ "$str1:u" = "$str2:u" ]] && echo  Strings Match! 
Strings Match!
>

This will convert both strings to uppercase before the comparison.


Another method makes use zsh s globbing flags, which allows us to directly make use of case-insensitive matching by using the i glob flag:

setopt extendedglob
[[ $str1 = (#i)$str2 ]] && echo "Match success"

# this example compares the variable with a literal string  match 
[[ $str1 = (#i)match ]] && echo "Match success"

For korn shell, I use typeset built-in command (-l for lower-case and -u for upper-case).

var=True
typeset -l var
if [[ $var == "true" ]]; then
    print "match"
fi

Very easy if you fgrep to do a case-insensitive line compare:

str1="MATCH"
str2="match"

if [[ $(fgrep -ix $str1 <<< $str2) ]]; then
    echo "case-insensitive match";
fi

Here is my solution using tr:

var1=match
var2=MATCH
var1=`echo $var1 | tr  [A-Z]   [a-z] `
var2=`echo $var2 | tr  [A-Z]   [a-z] `
if [ "$var1" = "$var2" ] ; then
  echo "MATCH"
fi

grep has a -i flag which means case insensitive so ask it to tell you if var2 is in var1.

var1=match 
var2=MATCH 
if echo $var1 | grep -i "^${var2}$" > /dev/null ; then
    echo "MATCH"
fi

shopt -s nocaseglob

The tr utility (translate characters) is always present on all Unix/Linux machines, and is light-weight.

Here is a function that can be used to address case insensitive comparisons. Since the exact location of tr can vary, we first probe its likely locations and store the correct location in an env var appropriately named "BIN_TR".

declare BIN_TR=$( ls /bin/tr /usr/bin/tr 2>/dev/null | head -1 );

That is then used in the function declaration.

toLowerCase() {
  echo "$*" | $BIN_TR  [:upper:]   [:lower:] 
}

A solution using tr is expected to be highly portable between different variations of OS and OS set-up. While awk is also highly probable, the tr utility is tiny compared to awk , and so a function using tr is presumably lighter weight.

On Unix-like operating systems, the test command checks file types and compares values.

str1="MATCH"
str2="match"

if test $str1 =  $str2
  then
  echo "equal yes"
else
  echo "equal not"
fi

On Unix-like operating systems, the test command checks file types and compares values.

it s very simple that way.

in a few lines of code





相关问题
Simple JAVA: Password Verifier problem

I have a simple problem that says: A password for xyz corporation is supposed to be 6 characters long and made up of a combination of letters and digits. Write a program fragment to read in a string ...

Case insensitive comparison of strings in shell script

The == operator is used to compare two strings in shell script. However, I want to compare two strings ignoring case, how can it be done? Is there any standard command for this?

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

String initialization with pair of iterators

I m trying to initialize string with iterators and something like this works: ifstream fin("tmp.txt"); istream_iterator<char> in_i(fin), eos; //here eos is 1 over the end string s(in_i, ...

break a string in parts

I have a string "pc1|pc2|pc3|" I want to get each word on different line like: pc1 pc2 pc3 I need to do this in C#... any suggestions??

Quick padding of a string in Delphi

I was trying to speed up a certain routine in an application, and my profiler, AQTime, identified one method in particular as a bottleneck. The method has been with us for years, and is part of a "...

热门标签