I am looking to do something like this in KSH:
if (( $var = (foo|bar)[0-9]*$ )); then
print "variable matched regex"
fi
Is it possible at all?
For the record I'm using Ksh Version M-11/16/88i
on a Solaris 10 machine.
5 Answers 5
Ksh has regular expressions, but not in the usual syntax (not in the version in Solaris 10).
if [[ $var = *@(foo|bar)*([0-9]) ]]; then ...
In the manual, look under "conditional expressions" for what's inside the brackets and under "file name generation" for the pattern syntax.
-
This is a pattern match, not a regular expression match (which uses the
=~
operator).chepner– chepner2015年11月06日 22:42:58 +00:00Commented Nov 6, 2015 at 22:42 -
1@chepner It doesn't use regex syntax, but it is a regular expression. Ksh patterns include all regular expression operators.Gilles 'SO- stop being evil'– Gilles 'SO- stop being evil'2015年11月06日 22:47:34 +00:00Commented Nov 6, 2015 at 22:47
-
what does the
*@
in the regular expression stands for ?Ali BENALI– Ali BENALI2021年08月23日 10:27:39 +00:00Commented Aug 23, 2021 at 10:27 -
1@Ali In the ksh regular expression syntax (which is not the usual regex syntax),
*
stands for any sequence of characters and@(foo|bar)
matches eitherfoo
orbar
.Gilles 'SO- stop being evil'– Gilles 'SO- stop being evil'2021年08月23日 21:20:39 +00:00Commented Aug 23, 2021 at 21:20 -
In this case, the
*([0-9])
says to match zero or more occurrences of what is in the parens, NOT any sequence of characters. Observe, the regexp will not passvar="bar##3"
. Meanwhile, it will passvar
if we have to have zero or more digits. as invar="bar321"
user1683793– user16837932022年01月06日 00:04:51 +00:00Commented Jan 6, 2022 at 0:04
Using case
with glob patterns might work for you.
The composite pattern *(pattern-list)
means "Matches zero or more occurrences of the given patterns" and @(pattern-list)
means "Matches exactly one of the given patterns."
matcher() {
typeset var="1ドル"
case "$var" in
*@(foo|bar)*([0-9])) print "$var matched" ;;
*) print "$var did not match" ;;
esac
}
for var in foo bar baz foo123 abc_foo132 abc_foo123z bar1 1bar1 1bar1a; do
matcher "$var"
done
Outputs:
foo matched
bar matched
baz did not match
foo123 matched
abc_foo132 matched
abc_foo123z did not match
bar1 matched
1bar1 matched
1bar1a did not match
Why not use egrep(1)? Gives you all a regex user could wish for:
if echo "$var" | egrep -s '(foo|bar)[0-9]*$' # -s means "silent"
then
...
Additional note for Solaris: With Solaris you may want to check the manpage for egrep - there is annother egrep version that is located at /usr/xpg4/bin/egrep
that supports some more options and differs in functionality when it comes to advanced regex stuff.
-
1sometimes Solaris will have GNU Egrep installed as well, as gegrep. Either from the Companion CD, or from SunFreeWare, and usually in /opt/sfw/bin or /usr/local/bin.Tim Kennedy– Tim Kennedy2011年10月20日 19:52:19 +00:00Commented Oct 20, 2011 at 19:52
-
@Tim: true, but I'd never rely on that. From my experience with customer production systems you'd better stick to what the base OS provides since what we would consider cool and helpful is often not allowed in production. +1 anyway ;-)ktf– ktf2011年10月21日 11:50:58 +00:00Commented Oct 21, 2011 at 11:50
-
100% agreed. i try to always use scripts/programs/perl modules that are installed by default. keeps things portable.Tim Kennedy– Tim Kennedy2011年10月22日 04:57:21 +00:00Commented Oct 22, 2011 at 4:57
I did something like this, using sed
. I don't know how good it is, but at least it worked ^^
if [ -z "$(echo "$var" | sed -e 's/(foo|bar)[0-9]*$//')" ]; then
print "variable matched regex"
fi
-
You need to put double quotes around variable substitutions, as always (otherwise you'll get wrong results or errors on some inputs containing wildcard characters or whitespace). Even with the right quoting, this assumes that the input doesn't contain a newline. Furthermore, your method is highly convoluted;
grep
is more natural, but there's a way that's built into ksh.Gilles 'SO- stop being evil'– Gilles 'SO- stop being evil'2011年10月20日 16:47:05 +00:00Commented Oct 20, 2011 at 16:47
I know I'm late to the party, but instead of ktf's solution:
if echo "$var" | egrep -s '(foo|bar)[0-9]*$' # -s means "silent"
then
...
you may also use
if grep -q '(foo|bar)[0-9]*$' <<< "$var" # -q means "quiet" ;-)
then
...
This technique with the <<<
operator is called the herestring. However, I should also add a warning: this WON'T work under a read-only environment (i. e. you will get ugly error messages to stderr
), since the herestring requires a temporary file to be written to somewhere. As far as I know, the "classic" way with echo
and a pipe will also work without any write permission at all.
You must log in to answer this question.
Explore related questions
See similar questions with these tags.
[foo|bar]
means "match a single character from the set (a,b,f,o,r,|)"? If you mean "match 'foo' or 'bar'" you want(foo|bar)