* character evaluating too soon - Help!

I have a user defined configuration file, which could contain the following type of entries:

directory_001=/a/directory/structure
pattern_001=fred*
pattern_002=*

I have a script which reads the file generically which will loop round

loop 1
genvar=�directory�
iteration=�001�

eval varcontents=�\$genvar�_�$iteration�

expected results varcontents=/a/directory/structure

loop 2
genvar=�pattern�
iteration=�001�

eval varcontents=�\$genvar�_�$iteration�

expected results varcontents=�fred*�

The above appears to work fine, however, the problem arises with loop 3

loop3
genvar=�pattern�
iteration=�002�

eval varcontents=�\$genvar�_�$iteration�

expected results varcontents=�*�
actual results are an error pattern_002: parameter not set

I realise what is happening and can resolve the problem by using pattern_002=\* in the config file. The problem is that the file is user created and it may be that someone will forget the backslash before the *.

Can someone suggest a way to resolve this so that a * without a backslash can be used in the configuration file please?

Many thanks for your help,
Helen :confused:

To preserve characters with a special meaning to the shell you have to protect them - usually by quoting them. Without knowing your actual code: if using \* instead of * solves your problem chances are that somewhere in your script you use your variable containing the asterisk without quoting: $variable instead of "$variable".

I suggest you look carefully through your code for such occasions, it might very well solve your problem.

Hope this helps.

bakunin

You could set -o noglob before the eval and then set +o noglob after.

Hi Bakunin,

The issue, I believe, is the eval statement. However I need to use the eval statement to get the contents of the variable.

Cheers
Helen

Hi Grasper,

I tried that but it gets the same error. I'm not sure what noglob does.

Out of interest it HPUX 11.00 and Korn shell.

Cheers
Helen

Apologies, I may have been a bit hasty in suggesting that in that way. noglob prevents wildcard characters from being expanded.

I don't know exactly how you'll be extracting your variables from the file or using them in your script, but here's a bit of code which uses eval in a similar way to the way you seem to need it and allows the asterisk character to be preserved:-

#!/bin/ksh

set -o noglob
pattern_002=*
set +o noglob
echo "PATTERN $pattern_002"

genvar="pattern"
iteration="002"

varc=$"$genvar"_"$iteration"
eval varcontents=$varc

set -o noglob
echo $varcontents
set +o noglob

When I run this I get the output:-

PATTERN *
PATTERN *
Hope that's of some use

Hi Helen,

the eval-statement will surely leave the asterisk unprotected. In this case the only way to deal with it is to escape it in the script itself:

'sed s/\*/\\&/g'

Hope this helps even better. ;-))

PS: "noglobber" or the equivalent parameter "-f" prevents filename substitution. The problem is that an "eval ..." might take precedence (i have never tested that).

bakunin

Hi Grasper,

I like your thinking, the problem I have is that in trying to simplify the issue so I don't put pages of coding on here, is that the issue is missed!

I tried your script and it works, however its in a slightly different context from mine.

In my script, the pattern_002=* is within a configuration file and a generic search of the configuration file is the way the pattern is pulled back.

The actual code from my script is a function which is launched as follows

fn_read_config "$v_search" "$v_iter" 002

in this case v_search is pattern and v_iter is 002

function fn_read_config {

p_search_item=$1
p_iteration=$2

grep ^"$p_search_item"_"$p_iteration" "$c_config_dir/$c_config_file" >/dev/null
v_search_return_code=$?

if [ $v_search_return_code -eq 0 ]
then
v_search_return=`grep ^"$p_search_item"_"$p_iteration" "$c_config_dir/$c_c
onfig_file"`
v_search_line=`print ${v_search_return#*=}`
return 0
fi
}

from this I wanted v_search_line to be *
I can't use the noglob when doing the search as I need the variables to be expanded.

I hope you understand, I did want to keep this as simple as possible!

Cheers
Helen

Hi Bakunin,

Thanks for your reply. The pattern may not always be a * so I could not run sed on it every time. I cannot check to see if the pattern is a * as it has already been evaluated! :wink:

Cheers
Helen

Hi Helen

I think the issue with variable-expansion and noglob is only a problem when doing your 'eval'. Setting noglob to on shouldn't affect it otherwise. I think I'm roughly using your code-structure in the following:-

#!/bin/ksh

function fn_read_config {

p_search_item=$1
p_iteration=$2

grep ^"$p_search_item"_"$p_iteration" ./paramfile >/dev/null
v_search_return_code=$?

if [ $v_search_return_code -eq 0 ]
then
v_search_return=`grep ^"$p_search_item"_"$p_iteration" ./paramfile`
set -o noglob
v_search_line=`print ${v_search_return#*=}`
echo "PATTERN $v_search_line"
set +o noglob
return 0
fi
}

v_search=pattern
v_iter=002

fn_read_config "$v_search" "$v_iter"

set -o noglob
echo "PATTERN $v_search_line"
set +o noglob

And I'm still able to get the output:-

PATTERN *
PATTERN *

I suppose it could depend on how you were using the resulting variable value, but I'm guessing it could still be possible by manipluating noglob.

Cheers

Maybe i don't get your point, but in the code snippet you provided i see several occasions where a quote would help. I tried the following code and it worked for every special char i tried in the input file - even without setting noglob. It should cover all the operations you used in your script save for the eval:

#!/bin/ksh

function func {

typeset var1="$1"
typeset var2="$2"

print - "Output from func(): var1=\"$var1\"\tvar2=\"$var2\""

return 0
}

# main()

typeset mvar1=""
typeset mvar2=""

cat input_file_with_codes | while read line ; do
     mvar1="$(print - "$line" | sed 's/  */ /g' | cut -d' ' -f1)"
     mvar2="$(print - "$line" | sed 's/  */ /g' | cut -d' ' -f2)"
     print - "mvar1=\"$mvar1\"\tmvar2=\"$mvar2\""
     func "$mvar1" "$mvar2"
done

exit 0

To write a small sed function which escapes every special character for exactly the eval should be no problem:

#!/bin/ksh

function escape_it {
typeset input="$1"
typeset output=""

output="$(print - "$input" | sed 's/[*?|]/\\&/g')"
print - "$output"

return 0
}

# main()

# ... do whatever ...

tmpvar="$(escape_it "$var")"
eval $tmpvar

# ... rest of your code ...

exit 0

Hi Bakunin and Grasper,

Thank-you both for your help. In the end I pre-parsed the config file with the sed statement to escape any special characters. I then used the resulting output as the config file. This worked fine.

Many thanks for all your time and patience!
Cheers
Helen :slight_smile: