Saving function output into a variable named in an argument

不羁的心 提交于 2020-02-08 10:14:09

问题


I have an interesting problem that I can't seem to find the answer for. I am creating a simple app that will help my dev department auto launch docker containers with NginX and config files. My problem is, for some reason I can't get the bash script to store the name of a folder, while scanning the directory. Here is an extremely simple example of what I am talking about....

#!/bin/bash

getFolder() {
    local __myResultFolder=$1
    local folder
    for d in */ ; do
        $folder=$d
    done
    __myResultFolder=$folder
    return $folder
}

getFolder FOLDER

echo "Using folder: $FOLDER"

I then save that simple script as folder_test.sh and put it in a folder where there is only one folder, change owner to me, and give it correct permissions. However, when I run the script I keep getting the error...

./folder_test.sh: 8 ./folder_test.sh: =test_folder/: not found

I have tried putting the $folder=$d part in different types of quotes, but nothing works. I have tried $folder="'"$d"'", $folder=`$d`, $folder="$d" but none of it works. Driving me insane, any help would be greatly appreciated. Thank you.


回答1:


The culprit is the line

$folder=$d

which is treating the folder names to stored with a = sign before and tried to expand it in that name i.e. literally treats the name =test_folder/ as an executable to be run under shell but does not find a file of that name. Change it to

folder=$d

Also, bash functions' return value is only restricted to integer types and you cannot send a string to the calling function. If you wanted to send a non-zero return code to the calling function on $folder being empty you could add a line

if [ -z "$folder" ]; then return 1; else return 0; fi

(or) if you want to return a string value from the function, do not use return, just do echo of the name and use command-substitution with the function name, i.e.

getFolder() {
    local __myResultFolder=$1
    local folder
    for d in */ ; do
        folder=$d
    done
    __myResultFolder=$folder
    echo "$folder"
}

folderName=$(getFolder FOLDER)
echo "$folderName"



回答2:


If you want to save your result into a named variable, what you're doing is called "indirect assignment"; it's covered in BashFAQ #6.

One way is the following:

#!/bin/bash
#      ^^^^ not /bin/sh; bash is needed for printf -v

getFolder() {
  local __myResultFolder=$1
  local folder d
  for d in */ ; do
    folder=$d
  done
  printf -v "$__myResultFolder" %s "$folder"
}

getFolder folderName
echo "$folderName"

Other approaches include:

  • Using read:

    IFS= read -r -d '' "$__myResultFolder" < <(printf '%s\0' "$folder")
    
  • Using eval (very, very carefully):

    # note \$folder -- we're only trusting the destination variable name
    # ...not trusting the content.
    eval "$__myResultFolder=\$folder"
    
  • Using namevars (only if using new versions of bash):

    getFolder() {
      local -n __myResultFolder=$1
      # ...your other logic here...
      __myResultFolder=$folder
    }
    


来源:https://stackoverflow.com/questions/41450156/saving-function-output-into-a-variable-named-in-an-argument

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!