Double Substitution variables in ksh

Hi

I have a variable whose value is like this
i=/test/test1/test2/myfile.cd.070505123457
i would like to have the value of myfile.cd stored into another variable

my attempt is
test=${i##*/} ;echo $test ##and i get
myfile.cd.070505123457

since what i wnat is myfile.cd i try this
test={{${i##*/}}##.} ;echo $test
and i get an error

Any idea how do i get what i want ?

regards
xiamin

i=/test/test1/test2/myfile.cd.070505123457
test=${i##*/}
test=${test%.*}

Hi Anbu

Thanks for your reply
I was wundering if we could do that in one line

regards
xiamin

Try...

test=$(expr $i : '.*/\(.*\)\..*')

Hi Ygor

Your solution works like charm..

But now i am pulling my hair out trying to understand what magic your code tries to do...

Can you please explain or else i might go bald :slight_smile:

regards
Hrishy

i=/test/test1/test2/myfile.cd.070505123457 ; test=${i##*/} ; test=${test%.*}

Sorry, I couldn't resist... :slight_smile:

Hi Perderabo

Your welcome :slight_smile:

Sometimes we are tempted and take the bait ;-).I guess you are seduced by unix

regards
Hrishy

Another...

test=$(basename $i .${i##*.})

Hi Ygor

I have two solutions from you ..but before you bring out your magic wand again..can you share the trick please or better if you could pass on the magic wand itself :slight_smile:

regards
Hrishy

The "magic" can be found in the man pages.

   `expr' supports pattern matching and other string operators.  

`STRING : REGEX'
     Perform pattern matching.  The arguments are converted to strings
     and the second is considered to be a (basic, a la GNU `grep')
     regular expression, with a `^' implicitly prepended.  The first
     argument is then matched against this regular expression.

     If the match succeeds and REGEX uses `\(' and `\)', the `:'
     expression returns the part of STRING that matched the
     subexpression.

And...

   `basename' removes any leading directory components from NAME.
Synopsis:

     basename NAME [SUFFIX]

   If SUFFIX is specified and is identical to the end of NAME, it is
removed from NAME as well. 

The following solution works fine under zsh ( but i don't think that there is many people using this shell), others shells give the error 'bad substitution' :

test=${${i##*/}%.*}

Jean-Pierre.

Hi

I am sorry i still did not understand the regular expression.

What does this regular expression mean

'.*/\(.*\)\..*'

can somebody deciper that in plain english

regards
xiamin

. Match any single character

  • Match any number (or none) of the single character that immediately precedes it.

.* means "match any number of any character."

\ turn off the special meaning of the following character

.*/ match /test/test1/test2/

\..* match .070505123457

\(.*\) match myfile.cd

Hi Anbu

Thanks suddenly all that cryptic character seems so clear.I dont even have to wear my contacts

regards
xiamin

Hi

I am even more confused regarding this regular expression

'.*/\(.*\)\..*'

can somebody please explain that.

I tried googling on this but that did not help much

Well maybe this will help... the pieces in red are special:
'.*/\(.*\)\..'
They define the beginning and end of a saved field. This is what will be be returned. The stuff to letf of the saved field is .
/ which matches everything up to a slash. Inside the saved field we have .* which seems to say match any characters. But we can't match literally everything, we have to save (just) enough for the rest of the expression to work. So after the saved field we have \..* which says match a dot followed by any characters.

Yes,
unfortunately ...

Hi Perderabo

Thanks for the wunderful explanation

so what i understand is
./ Matches upto /
\(.
\) Matches and saves myfile.cd.070505123457
\..* Match a dot followed by any characters

So shouldnt this match just cd.070505123457 and the whole expression return myfile how come it is returning myfile.cd

Thanks for being so patient with me.

regards
Hrishy

Regular expression quantifiers are greedy, so "*" means match as much as possible.

./ Matches any characters upto the last /
\(.
\)\. Matches and returns any characters upto the last .
.* not actually required. (I originally thought that this was required because expr regular expressions are anchored, but it turns out that they are only achored to the start of the expression.)

Hi Ygor

Thanks ..a million i got it.

Gotta remember this "regular expressions are greedy "

regards
Hrishy