1

I have done a script on a machine with this command on it

printf -v $1 %s $2

It's working fine on the server that I am using. But when I copied the scripts to another server, I get this error. What am I missing here?

EDIT: What the code does to my script is it declares variables, but is not localized on a function. Here's the complete function

#Declare each property=value as regular bash variable=value
function getProperty {
    for x in $(echo ${1} | tr ":" "\n")
    do
        set -- $(echo ${x} | tr "=" "\n")
        printf -v $1 %s $2
        #I tried using declare, but the variables become localized to this function only
    done
}
makalshrek
  • 853
  • 3
  • 14
  • 29
  • Same system? Compare the `man` pages. – Alex Chamberlain Aug 15 '12 at 09:34
  • I looked on the man pages, and they are different. If it is the case, then what other approach I can do to declare a variable in a function? (The variable must be seen by other functions, so using declare is I think not suitable because I don't want to localize the variables.) – makalshrek Aug 15 '12 at 09:38
  • 1
    Can you edit your question to explain what `-v` does? I've not used it before, but I think I understand what you want to achieve. – Alex Chamberlain Aug 15 '12 at 09:39
  • @Alex I have really no idea what the -v switch does. I was just advised to use it to globalize the variables that I am declaring. See http://stackoverflow.com/questions/11776468/create-associative-array-in-bash-3/11776875#11776875 – makalshrek Aug 15 '12 at 09:43

2 Answers2

2

Will export work?

export "${1}=$(printf %s "$2")"

I might be barking up the wrong tree here...

Alex Chamberlain
  • 4,147
  • 2
  • 22
  • 49
  • 1
    For somewhat complicated reasons, it's best to quote the entire argument if attempting to do an expansion on the lvalue. The export attribute remains after the function returns as a side-effect. Also, don't use backticks. `export "${1}=$(printf %s "$2")"` – ormaaj Aug 15 '12 at 09:57
  • @ormaaj Would you like to suggest an edit, so you get the credit? – Alex Chamberlain Aug 15 '12 at 10:00
  • Tried using export "${1}=$(printf %s "$2")". It works. Thanks. – makalshrek Aug 15 '12 at 10:24
  • Another question: if I use export, will the variables set be cleared from the environment once the script has finished executing? – makalshrek Aug 15 '12 at 10:30
  • @SciasTwentyThree, No the export only means variable is set for subprocess, the only way to keep variable after a script has finished is to `source the_script` (equivalent to `. the_script`) which doesn't spawn a subprocess but executes commands in it with current shell, also use return instead of exit to not exit the current sheel – Nahuel Fouilleul Aug 15 '12 at 11:00
1

Looks like you're trying to take some input in the form of:

var=value:var=value

This will fail if any part of the input contains whitespace, newlines, or glob characters. See: don't read lines with for. It will also fail if the first parameter is ever empty. Because your expansions are unquoted you're dealing with multiple passes of globbing and word-splitting which will probably lead to problems.

Unfortunately, indirect assignment is one of the biggest failures of Bash. If you do this a lot you should seriously consider switching the entire script to ksh where you can use nameref variables. It's very worth it just for that one feature. (The next version of Bash should solve this).

You should use arrays to deal with collections. If you need to deal with key-value pairs like this then you should use Bash 4 and associative arrays. printf -v is the best way to do indirect assignment to an outer scope in a recent enough Bash. If you have Bash 4.2 then you can use declare -g to assign to a global. If your bash is too old to do any of this, upgrade.

Some techniques plus how to use associative arrays are explained here: http://mywiki.wooledge.org/BashFAQ/006

Also read up on how to quote.

ormaaj
  • 6,201
  • 29
  • 34
  • I have tried using associative arrays but the bash on the system here at work is not version 4. So I had to make a sort of hack to accomplish what I want to do. – makalshrek Aug 16 '12 at 02:11