Unix Shell - Case-insensitive matching in bash - Again

This is Interesting: Free IT Magazines  
Home > Archive > Unix Shell > February 2005 > Case-insensitive matching in bash - Again





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Case-insensitive matching in bash - Again
CV

2005-02-24, 5:58 pm


I didn't get around to trying this until now, so
I continue here, in a new thread:

The question is still the same: How can I perform case-insensitive
string matching in bash without calling an external program such
as grep ?

William Park wrote:
....
>
>
> It should work for 'case' statement.


It doesn't, actually:

~$ ccc() { shopt -s nocaseglob; case $1 in *abc*) echo "abc found";; *) echo "not found";; esac; }
~$ ccc sdaabcvgasfdg
abc found
~$ ccc sdaAbcvgasfdg
not found
~$

According to the manpage nocaseglob works for filename expansion.
It doesn't say anything about string matching.

Regards CV
Chris F.A. Johnson

2005-02-24, 5:58 pm

On Thu, 24 Feb 2005 at 14:22 GMT, CV wrote:
>
> I didn't get around to trying this until now, so
> I continue here, in a new thread:
>
> The question is still the same: How can I perform case-insensitive
> string matching in bash without calling an external program such
> as grep ?


It looks long, but this is still quicker than calling grep unless
the pattern is longer than ~35 characters (YMMV).

ccc() ## Your function
{
case $1 in
*$_IPAT*) echo "$pat found";;
*) echo "not found";;
esac
}

_ocase() { ## Switch case of $1 (requires $upper and $lower to be defined)
case $1 in
[a-z]) idx=${lower%$1*}
_OCASE=${upper:${#idx}:1}
;;
[A-Z]) idx=${upper%$1*}
_OCASE=${lower:${#idx}:1}
;;
*) _OCASE=$1 ;;
esac
}

_ipat() ## Create case-insensitive pattern from $1
{
word=${1}
_IPAT=

while [ -n "$word" ]
do
the_rest=${word#?}
first=${word%"$the_rest"}
_ocase "$first"
_IPAT=$_IPAT\[$first$_OCASE\]
word=$the_rest
done
}

lower=thequickbrownfxjmpsvlazydg
upper=THEQUICKBROWNFXJMPSVLAZYDG

str=$1
pat=$2
_ipat "$pat"
ccc "$str"


--
Chris F.A. Johnson http://cfaj.freeshell.org/shell
========================================
===========================
My code (if any) in this post is copyright 2005, Chris F.A. Johnson
and may be copied under the terms of the GNU General Public License
Icarus Sparry

2005-02-24, 5:58 pm

On 2005-02-24, CV <or254498@hotmail.com> wrote:
>
> I didn't get around to trying this until now, so
> I continue here, in a new thread:
>
> The question is still the same: How can I perform case-insensitive
> string matching in bash without calling an external program such
> as grep ?
>
> William Park wrote:
> ...
>
> It doesn't, actually:
>
> ~$ ccc() { shopt -s nocaseglob; case $1 in *abc*) echo "abc found";; *) echo "not found";; esac; }
> ~$ ccc sdaabcvgasfdg
> abc found
> ~$ ccc sdaAbcvgasfdg
> not found
> ~$
>
> According to the manpage nocaseglob works for filename expansion.
> It doesn't say anything about string matching.


If you are willing to switch to regular expressions, then the manual
tells you that the =~ operator will obey the nocaseglob for strings

ccc(){
# arrange for nocaseglob to be the same before and after
# this routine
setter=-u
if shopt -q nocaseglob
then
setter=-s
fi
shopt -s nocaseglob
# Do the compare in a case insensitive manner
if [[ $1 =~ ".*abc.*" ]]
then
shopt $setter nocaseglob
return 0
else
shopt $setter nocaseglob
return 1
fi
}


William Park

2005-02-24, 5:58 pm

CV <or254498@hotmail.com> wrote:
>
> I didn't get around to trying this until now, so
> I continue here, in a new thread:
>
> The question is still the same: How can I perform case-insensitive
> string matching in bash without calling an external program such
> as grep ?


> William Park wrote:
....[vbcol=seagreen]
> It doesn't, actually:

....
> According to the manpage nocaseglob works for filename expansion.
> It doesn't say anything about string matching.


Yeah, manpage is a bit ambiguous. 'nocaseglob' does not work for 'case'
or '[[...]]'. If you don't want to use external program, then you can
apply my patch for Bash (http://freshmeat.net/projects/bashdiff/).

Then, you can use regex in 'case' statement, like
shopt -s nocaseglob
case Abc123 in
abc)) echo found abc ;;
esac
where '))' denotes regex instead of the usual glob. There is
comprehensive helpfile, so
help case

--
William Park <opengeometry@yahoo.ca>, Toronto, Canada
Slackware Linux -- because I can type.

CV

2005-02-24, 5:58 pm

Icarus Sparry wrote:

> If you are willing to switch to regular expressions, then the manual
> tells you that the =~ operator will obey the nocaseglob for strings
>
> ccc(){

....
> shopt -s nocaseglob
> # Do the compare in a case insensitive manner
> if [[ $1 =~ ".*abc.*" ]]
> then

....

That would be nice, but my bash version (version 2.05b.0(1)-release
(i686-pc-cygwin)) does not seem to know about this feature. It is
not mentioned in the man-page and the "=~" generates an error.

I suppose what you describe here will be in some later version
of bash (?)

Thanks all the same.
CV
CV

2005-02-25, 5:58 pm

Chris F.A. Johnson wrote:
> It looks long, but this is still quicker than calling grep unless
> the pattern is longer than ~35 characters (YMMV).


Nifty script, Chris.

Yes, I can easily believe this is faster than calling grep, especially
in cases where you only need to generate the pattern once, but the actual
string comparison is performed a large number of times.

Still, if one needs to go to these lengths maybe it is better to
go for PERL or something else for this.

Thanks to all who replied.
CV
Chris F.A. Johnson

2005-02-25, 5:58 pm

On Fri, 25 Feb 2005 at 15:48 GMT, CV wrote:
> Chris F.A. Johnson wrote:
>
> Nifty script, Chris.
>
> Yes, I can easily believe this is faster than calling grep, especially
> in cases where you only need to generate the pattern once, but the actual
> string comparison is performed a large number of times.


Then you'll save time for each call, make it cumulatively MUCH
faster, especially on short strings.

> Still, if one needs to go to these lengths


What "lengths"? It's written; just put it in a file and source it
whenever you need it.

> maybe it is better to go for PERL or something else for this.


"Something else", perhaps.

--
Chris F.A. Johnson http://cfaj.freeshell.org/shell
========================================
===========================
My code (if any) in this post is copyright 2005, Chris F.A. Johnson
and may be copied under the terms of the GNU General Public License
CV

2005-02-25, 5:59 pm

Chris F.A. Johnson wrote:
> What "lengths"? It's written; just put it in a file and source it
> whenever you need it.


Readability, maintainability. Much as I admire the elegant bit of
wizardry that code is, it is not so obvious to see at a glance how
it works.

I like to be able to come back after a few months and easily
understand how the bits and pieces fit together, perhaps to
modify the code, perhaps to base some new design on it.

Cheers CV
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com