Bash:Substring Extraction

Bash:Substring Extraction

am 13.12.2005 05:27:46 von karthicksmail

Hi,

Can you give me a way to get the substring from a variable that is
portable to older versions of bash?
When I try
echo ${VAR:0:5}
It works in a setup having 2.05b.0(1) release of bash but fails with
another setup having 1.14.7(1) version. In the latter, I am getting the
error:
bash: ${VAR:0:5}: bad substitution

I am not in a position to upgrade the bash version in the second
machine.

Thanks and regards,
Karthick S.

Re: Bash:Substring Extraction

am 13.12.2005 05:47:14 von Ed Morton

Karthick S. wrote:
> Hi,
>
> Can you give me a way to get the substring from a variable that is
> portable to older versions of bash?
> When I try
> echo ${VAR:0:5}
> It works in a setup having 2.05b.0(1) release of bash but fails with
> another setup having 1.14.7(1) version. In the latter, I am getting the
> error:
> bash: ${VAR:0:5}: bad substitution
>
> I am not in a position to upgrade the bash version in the second
> machine.

$ VAR="abcdefghi"
$ eval echo "\${VAR%${VAR#?????}}"
abcde

Regards,

Ed.

Re: Bash:Substring Extraction

am 13.12.2005 06:04:52 von karthicksmail

Ed Morton wrote:
> $ VAR="abcdefghi"
> $ eval echo "\${VAR%${VAR#?????}}"
> abcde

Hi,

Thanks a lot. That works.

But would it be possible for you to explain it?

Thanks and regards,
Karthick S.

Re: Bash:Substring Extraction

am 13.12.2005 17:20:49 von cfajohnson

On 2005-12-13, Karthick S. wrote:
> Hi,
>
> Can you give me a way to get the substring from a variable that is
> portable to older versions of bash?
> When I try
> echo ${VAR:0:5}
> It works in a setup having 2.05b.0(1) release of bash but fails with
> another setup having 1.14.7(1) version. In the latter, I am getting the
> error:
> bash: ${VAR:0:5}: bad substitution
>
> I am not in a position to upgrade the bash version in the second
> machine.

Most versions of expr have a substr expression:

expr substr "$VAR" 1 5

If you want to keep it in the shell itself, this is faster than
expr and will work in any POSIX shell. This comes from Chapter 3 of
"Shell Scripting Recipes":

_substr()
{
_SUBSTR=

## store the parameters
ss_str=$1
ss_first=$2
ss_length=${3:-${#ss_str}}

## return an error if the first character wanted is beyond end of string
if [ $ss_first -gt ${#ss_str} ]
then
return 1
fi

if [ $ss_first -gt 1 ]
then
## build a string of question marks to use as a wildcard pattern
_repeat "?" $(( $ss_first - 1 ))

## remove the beginning of string
ss_str=${ss_str#$_REPEAT}
elif [ ${ss_first} -lt 0 ] ## ${#ss_str} ]
then
## count from end of string
_repeat "?" ${ss_first#-}

## remove the beginning
ss_str=${ss_str#${ss_str%$_REPEAT}}
fi

## ss_str now begins at the point we want to start extracting
## print the desired number of characters
if [ ${#ss_str} -gt $ss_length ]
then
_repeat "${ss_wild:-??}" $ss_length
ss_wild=$_REPEAT
_SUBSTR=${ss_str%${ss_str#$ss_wild}}
else
_SUBSTR=${ss_str}
fi
}

substr()
{
_substr "$@" && printf "%s\n" "$_SUBSTR"
}

_repeat()
{
## If the first argument is -n, repeat the string N times
## otherwise repeat it to a length of N characters
case $1 in
-n) shift
r_num=$(( ${#1} * $2 ))
;;
*) r_num=$2
;;
esac
r_str=$1
_REPEAT=$1
while [ ${#_REPEAT} -lt ${r_num} ]
do
if [ $(( ${#_REPEAT} * 2 )) -gt $r_num ]
then
while [ ${#_REPEAT} -lt $r_num ]
do
_REPEAT=$_REPEAT$r_str
done
elif [ $(( ${#_REPEAT} * 2 )) -eq $r_num ]
then
_REPEAT=$_REPEAT$_REPEAT
else
## The length builds rapidly by concatenating 3 copies in each loop
## Your results may be different, but I have found that three is
## the optimum number; try it with more, if you like
_REPEAT=$_REPEAT$_REPEAT$_REPEAT
fi
done
while [ ${#_REPEAT} -gt $r_num ]
do
_REPEAT=${_REPEAT%?}
done
}

case $BASH_VERSION in
[2-9]*)
_sub() {
printf "%s\n" _SUB="${1/$2/$3}"
}
_gsub() { _GSUB="${1//$2/$3}"; }
;;
esac

--
Chris F.A. Johnson, author
Shell Scripting Recipes: A Problem-Solution Approach, 2005, Apress

Re: Bash:Substring Extraction

am 13.12.2005 19:12:22 von Ed Morton

Karthick S. wrote:
> Ed Morton wrote:
>
>>$ VAR="abcdefghi"
>>$ eval echo "\${VAR%${VAR#?????}}"
>>abcde
>
>
> Hi,
>
> Thanks a lot. That works.
>
> But would it be possible for you to explain it?
>
> Thanks and regards,
> Karthick S.
>


It's 2 steps:

1) select all but the first 5 characters from VAR:

${VAR#?????}

2) delete those characters from VAR:

\${VAR%those_characters}

You could do it with a tmp variable instead of using eval:

tmp="${VAR#?????}"
echo "${VAR%$tmp}"

Regards,

Ed.

Re: Bash:Substring Extraction

am 14.12.2005 23:02:06 von Icarus Sparry

On 2005-12-13, Ed Morton wrote:
>
>
> Karthick S. wrote:
>> Ed Morton wrote:
>>
>>>$ VAR="abcdefghi"
>>>$ eval echo "\${VAR%${VAR#?????}}"
>>>abcde
>>
>>
>> Hi,
>>
>> Thanks a lot. That works.
>>
>> But would it be possible for you to explain it?
>>
>> Thanks and regards,
>> Karthick S.
>>
>
>
> It's 2 steps:
>
> 1) select all but the first 5 characters from VAR:
>
> ${VAR#?????}
>
> 2) delete those characters from VAR:
>
> \${VAR%those_characters}
>
> You could do it with a tmp variable instead of using eval:
>
> tmp="${VAR#?????}"
> echo "${VAR%$tmp}"
>
> Regards,
>
> Ed.

And you can avoid the 'eval' step as well.
echo "${VAR%${VAR#?????}}"

(Tested with bash 3 and ksh93)

Re: Bash:Substring Extraction

am 15.12.2005 05:39:14 von Ed Morton

Icarus Sparry wrote:
> On 2005-12-13, Ed Morton wrote:
>
>>
>>Karthick S. wrote:
>>
>>>Ed Morton wrote:
>>>
>>>
>>>>$ VAR="abcdefghi"
>>>>$ eval echo "\${VAR%${VAR#?????}}"
>>>>abcde
>>>
>>>
>>>Hi,
>>>
>>>Thanks a lot. That works.
>>>
>>>But would it be possible for you to explain it?
>>>
>>>Thanks and regards,
>>>Karthick S.
>>>
>>
>>
>>It's 2 steps:
>>
>>1) select all but the first 5 characters from VAR:
>>
>> ${VAR#?????}
>>
>>2) delete those characters from VAR:
>>
>> \${VAR%those_characters}
>>
>>You could do it with a tmp variable instead of using eval:
>>
>>tmp="${VAR#?????}"
>>echo "${VAR%$tmp}"
>>
>>Regards,
>>
>> Ed.
>
>
> And you can avoid the 'eval' step as well.
> echo "${VAR%${VAR#?????}}"
>
> (Tested with bash 3 and ksh93)

I think you missed the crucial part of this thread, which the OP snipped
earlier:

"Can you give me a way to get the substring from a variable that is
portable to older versions of bash?"

Regards,

Ed.