文档章节

如何从Bash函数返回字符串值

j
 javail
发布于 01/27 21:57
字数 1242
阅读 71
收藏 0

我想从Bash函数返回一个字符串。

我将用Java编写示例以显示我想做的事情:

public String getSomeString() {
  return "tadaa";
}

String variable = getSomeString();

下面的示例在bash中有效,但是有更好的方法吗?

function getSomeString {
   echo "tadaa"
}

VARIABLE=$(getSomeString)

#1楼

考虑以下代码,向Vicky Ronnen抬起头来:

function use_global
{
    eval "$1='changed using a global var'"
}

function capture_output
{
    echo "always changed"
}

function test_inside_a_func
{
    local _myvar='local starting value'
    echo "3. $_myvar"

    use_global '_myvar'
    echo "4. $_myvar"

    _myvar=$( capture_output )
    echo "5. $_myvar"
}

function only_difference
{
    local _myvar='local starting value'
    echo "7. $_myvar"

    local use_global '_myvar'
    echo "8. $_myvar"

    local _myvar=$( capture_output )
    echo "9. $_myvar"
}

declare myvar='global starting value'
echo "0. $myvar"

use_global 'myvar'
echo "1. $myvar"

myvar=$( capture_output )
echo "2. $myvar"

test_inside_a_func
echo "6. $_myvar" # this was local inside the above function

only_difference



会给

0. global starting value
1. changed using a global var
2. always changed
3. local starting value
4. changed using a global var
5. always changed
6. 
7. local starting value
8. local starting value
9. always changed

也许正常情况是使用test_inside_a_func函数中使用的语法,因此在大多数情况下都可以使用这两种方法,尽管捕获输出是在任何情况下始终可以使用的更安全的方法,模仿了您所返回的函数的返回值可以用其他语言找到,正如Vicky Ronnen正确指出的那样。


#2楼

agt@agtsoft:~/temp$ cat ./fc 
#!/bin/sh

fcall='function fcall { local res p=$1; shift; fname $*; eval "$p=$res"; }; fcall'

function f1 {
    res=$[($1+$2)*2];
}

function f2 {
    local a;
    eval ${fcall//fname/f1} a 2 3;
    echo f2:$a;
}

a=3;
f2;
echo after:a=$a, res=$res

agt@agtsoft:~/temp$ ./fc
f2:10
after:a=3, res=

#3楼

像上面的bstpierre一样,我使用并建议使用显式命名输出变量:

function some_func() # OUTVAR ARG1
{
   local _outvar=$1
   local _result # Use some naming convention to avoid OUTVARs to clash
   ... some processing ....
   eval $_outvar=\$_result # Instead of just =$_result
}

请注意使用引号$。 这样可以避免将$result内容解释为shell特殊字符。 我发现这比捕获回声的result=$(some_func "arg1")惯用语一个数量级 。 在MSYS上使用bash时,速度差异似乎更为明显,因为从函数调用捕获stdout几乎是灾难性的。

可以发送局部变量,因为局部变量在bash中动态作用域:

function another_func() # ARG
{
   local result
   some_func result "$1"
   echo result is $result
}

#4楼

正如其他人所写,最直接,最可靠的解决方案是使用命令替换:

assign()
{
    local x
    x="Test"
    echo "$x"
}

x=$(assign) # This assigns string "Test" to x

缺点是性能,因为这需要单独的过程。

本主题中建议的另一种技术,即传递要分配给变量的变量名称作为参数,会产生副作用,我不建议以其基本形式使用它。 问题是您可能需要在函数中使用一些变量来计算返回值,并且可能会发生的是,用于存储返回值的变量名称会干扰其中之一:

assign()
{
    local x
    x="Test"
    eval "$1=\$x"
}

assign y # This assigns string "Test" to y, as expected

assign x # This will NOT assign anything to x in this scope
         # because the name "x" is declared as local inside the function

当然,您可能不将函数的内部变量声明为局部变量,但实际上应始终这样做,否则,如果存在一个同名变量,则您可能会意外覆盖父作用域中不相关的变量。

一种可能的解决方法是将传递的变量显式声明为global:

assign()
{
    local x
    eval declare -g $1
    x="Test"
    eval "$1=\$x"
}

如果将名称“ x”作为参数传递,则函数主体的第二行将覆盖先前的本地声明。 但是名称本身可能仍然会干扰,因此,如果您打算使用先前存储在传递的变量中的值,然后再在其中写入返回值,请注意,您必须从一开始就将其复制到另一个局部变量中。 否则结果将不可预测! 此外,这仅适用于最新的BASH版本4.2。 更多可移植的代码可能会使用具有相同效果的显式条件构造:

assign()
{
    if [[ $1 != x ]]; then
      local x
    fi
    x="Test"
    eval "$1=\$x"
}

也许最优雅的解决方案只是为函数返回值保留一个全局名称,并在您编写的每个函数中一致地使用它。


#5楼

如前所述,从函数返回字符串的“正确”方法是使用命令替换。 如果该函数也需要输出到控制台(如@Mani所述),请在该函数的开头创建一个临时fd并重定向到控制台。 返回字符串之前,请关闭临时fd。

#!/bin/bash
# file:  func_return_test.sh
returnString() {
    exec 3>&1 >/dev/tty
    local s=$1
    s=${s:="some default string"}
    echo "writing directly to console"
    exec 3>&-     
    echo "$s"
}

my_string=$(returnString "$*")
echo "my_string:  [$my_string]"

执行没有参数的脚本会产生...

# ./func_return_test.sh
writing directly to console
my_string:  [some default string]

希望这可以帮助人们

-安迪

本文转载自:https://da.sofbug.com/question/Da3b

j
粉丝 5
博文 1092
码字总数 0
作品 0
深圳
私信 提问
怎样用 Bash 编程:逻辑操作符和 shell 扩展

学习逻辑操作符和 shell 扩展,本文是三篇 Bash 编程系列的第二篇。 Bash 是一种强大的编程语言,完美契合命令行和 shell 脚本。本系列(三篇文章,基于我的 三集 Linux 自学课程)讲解如何在...

作者: David Both
2019/12/17
0
0
shell脚本学习(Chapter 1)

涉及到的东西: * 脚本如何执行与脚本基本书写方式 * echo、printf终端打印 * 变量的赋值操作:没有引号、单引号、双引号 * 变量的取值 * 两个环境变量:PATH、PS1 * 数学运算方法:let、(( ...

心中的理想乡
2017/09/17
17
0
function-array--字符串截取--mktemp--install

function:函数 过程式编程;代码重用 模块化编程 结构化编程 语法一: funcion f_name{ 函数体 } 语法二: f_name (){ 函数体 } 调用:函数只有被调用才会执行: 函数的生命周期;被调用时创...

技术小胖子
2017/11/14
0
0
怎样用 Bash 编程:逻辑操作符和 shell 扩展 - 知乎

学习逻辑操作符和 shell 扩展,本文是三篇 Bash 编程系列的第二篇。 -- David Both(作者) Bash 是一种强大的编程语言,完美契合命令行和 shell 脚本。本系列(三篇文章,基于我的 三集 Li...

Linux 爱好者
2019/12/17
0
0
面试linux运维一定会问到Shell脚本这24个问题

虽然现在Python在运维工作中已经使用很普遍,但是很多企业在找Linux云计算工程师的时候还是会问到 shell 脚本的问题,它有助于你在工作环境中自动完成很多任务。 如下是一些面试过程中,经常...

tom_tuwei
2017/12/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Minecraft Fabric Client 教程 #5 添加Event、Sprint和ToggleCommand

首发于Enaium的个人博客 添加Event 下载 放在cn.enaium.excel里 然后在Excel.java里面添加EventManager public enum Excel { [...] public EventManager eventManager; pu......

Enaium
21分钟前
47
0
记 S3Service 代码中的一个低级错误

osgl-storage 是 osgl 工具箱 中用于简化存储的. 其特点是接口简单, 支持多种存储引擎插件, 包括本地文件系统, AWS S3, Azure Blob, 七牛 Kodo 服务. 最近老码农在一次调试中偶然发现了 osgl...

开源老码农
23分钟前
469
1
如何实现Samba文件共享服务

目标:实现Samba文件共享服务 试验环境:两台主机服务端:192.168.56.11客户端:192.168.56.12 配置用户认证共享 服务端操作: 1.关闭防火墙,关闭selunix [root@hejie ~]# setenforce 0[...

linuxprobe2020
25分钟前
38
0
SQL Server Profiler - 如何过滤跟踪以仅显示来自一个数据库的事件?

如何将SQL Server Profiler跟踪限制为特定数据库? 我看不到如何过滤跟踪,看不到我连接的实例上的所有数据库的事件。 #1楼 在Trace properties> Events Selection选项卡下>选择show all co...

技术盛宴
25分钟前
37
0
Kafka配置及常用命令笔记

一、kafka配置 1. 服务端 server.properties #broker 的全局唯一编号,不能重复broker.id=0#删除 topic 功能使能delete.topic.enable=true#处理网络请求的线程数量num.network.thr...

liddblog
29分钟前
31
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部