【问题标题】:How to get the return value from matlab in bash script?如何在 bash 脚本中从 matlab 获取返回值?
【发布时间】:2012-04-22 12:47:26
【问题描述】:

如果我有这个 matlab 函数

function [result] = matlab_test(param1, param2)

disp(sprintf('param1 : %s', param1));
disp(sprintf('param2 : %s', param2));

result = 'hello matlab';

我想在 bash 脚本中调用这个 matlab 函数,比如

matlab -nodesktop -nosplash -nodisplay -r "try, A=matlab_test('test','matlab'); end; quit"
echo $A

我想要这个输出

test
matlab
hello matlab

我在这里的要求是找出是否可以在我的 bash 脚本中使用来自 Matlab 的返回值,并通过管道传递它。我只想将我的应用程序分成小组件(文件)并通过管道/参数进行通信。简而言之,我想看看我可以在我的 bash 脚本中将 Matlab 脚本包装到多远,以便我可以设置我的代码架构。
如果我不能这样做,我将简单地将我需要从 matlab 返回值的部分捆绑到 matlab 脚本中。

【问题讨论】:

  • 我编辑了我的答案,试图回答你修改后的问题。
  • 如果返回值是一个小整数,一个简单的解决方案是使用exit(code) 命令将其作为Matlab 进程的退出代码返回。在 Windows 上尝试此操作时,不要忘记 matlab-wait 命令行参数。

标签: bash function matlab return-value


【解决方案1】:

您在这里尝试做两件事。首先:在 shell 中显示 Matlab 程序的输出。其次,在shell中分配一个变量。

当我尝试这个时,我发现 Matlab 会在标准输出上写满它的开头消息,所以我最终这样做了:

mkfifo ~/matlab_output
matlab ... > /dev/null & cat ~/matlab_output

然后在 matlab 中,将 sprintf 替换为:

f = fopen('~/matlab_output', 'w');
fprintf(f, 'param1 : %s', param1);
fclose(f);

这是您第一个要求的一种解决方案(您可以只写入一个普通文件,然后再对文件进行 cat 处理,但您必须为此使用 &&,所以在 Matlab 之前您不会看到输出完全完成了。)。您遇到的第二个问题 - 在 matlab 中执行“A = result”并能够在 shell 中“回显 $A” - 更难。你可以这样做:

mkfifo ~/matlab_commands
mkfifo ~/matlab_output
matlab ... > /dev/null & cat ~/matlab_output & eval $(cat ~/matlab_commands)

在matlab中:

f2 = fopen('~/matlab_commands', 'w');
fprintf(f2, 'A=%s', double2str(results));
fclose(f2);

但我真的不知道这会有多好。

【讨论】:

    【解决方案2】:

    你问了两个问题。我会回答这两个问题,包括为什么第二个可能是不可能的,具体取决于您的操作系统(在我的操作系统上绝对不可能),然后提供有关问题相关解决方法的建议。

    首先,我在让 Matlab 与 shell 交互时使用这样的脚本。

    #!/bin/sh 
    
    cat <<EOF | matlab -nodesktop -nosplash -nodisplay 
    A=matlab_test('$1','$2');
    system(['export temp1=' A]); %doesn't work
    setenv('temp2',A); %also doesn't work, I'll explain why below
    exit
    EOF
    echo $temp1
    echo $temp2
    

    给出输出:

    [XXXXXX@compute-0-138 ~]$ ./stack_ex test matlab
    Warning: No window system found.  Java option 'MWT' ignored
    
                                < M A T L A B (R) >
                      Copyright 1984-2010 The MathWorks, Inc.
                    Version 7.12.0.635 (R2011a) 64-bit (glnxa64)
                                   March 18, 2011
    
    
      To get started, type one of these: helpwin, helpdesk, or demo.
      For product information, visit www.mathworks.com.
    
    >> param1 : test
    param2 : matlab
    >> >> >> 
    

    很明显,设置环境变量的两个版本都行不通。这就引出了您的第二个问题。

    “回显”失败的原因是 systemsetenv 创建的 shell 在 Matlab 关闭时会关闭。也就是说,Matlab 不能在调用它的 shell 之外设置环境变量。

    in this posting 讨论的 Windows 系统有一个解决方法,它使用 Microsoft 的工具。还提到了here

    我不相信 *nix 系统可以从 Matlab 中设置环境变量。

    这是一种与您描述的类似的方法。

    我假设使用 echo 不是您真正想要做的。相反,我猜您想使用存储在环境变量中的字符串输出,以便进一步处理 shell 中的命令或脚本。一种可能的解决方法如下:

    #!/bin/sh 
    
    cat <<EOF | matlab -nodesktop -nosplash -nodisplay 
    A=matlab_test('$1','$2');
    setenv('temp1',A); %doesn't work
    [a b] = system(['echo ' '$' 'temp1'])
    exit
    EOF
    

    给出输出: [XXXXXX@compute-0-138 ~]$ ./stack_ex_3 测试 matlab 警告:未找到窗口系统。 Java 选项“MWT”被忽略

                                < M A T L A B (R) >
                      Copyright 1984-2010 The MathWorks, Inc.
                    Version 7.12.0.635 (R2011a) 64-bit (glnxa64)
                                   March 18, 2011
    
    
      To get started, type one of these: helpwin, helpdesk, or demo.
      For product information, visit www.mathworks.com.
    
    >> param1 : test
    param2 : matlab
    >> >> 
    a =
    
         0
    
    
    b =
    
    hello matlab
    

    这表明命令echo $temp1setenv 创建的子shell 中进行了评估,并且temp1 保存了分配给它的值。这个对 shell 的调用的结果现在存储在 b 中(a 保持 0 表示成功)。可以想象,您可以通过 system 命令传递您想要在 shell 中执行的全部操作,以便它在子 shell 中运行。不过,我们必须了解您的问题的更多细节才能对这种方法进行全面评估。

    编辑和跟进 **********************

    我能想到的最接近包装 Matlab 和 bash 的方法是以下技巧。您可以使用以下命令将 Matlab 脚本的输出通过管道传输到 myresult.out

    #!/bin/sh 
    
    cat <<EOF | matlab -nodesktop -nosplash -nodisplay /> myresult.out 
    A=matlab_test('$1','$2');
    disp(['grepMe ' A])
    exit
    EOF
    

    您可以从myresult.out grep grepMe 行,通过管道传输到 sed,然后只选择您需要的输出行的一部分,然后在脚本的其余部分通过管道传输。这与我认为您可以实现的目标一样接近。

    【讨论】:

    • 请查看我的问题中的更新以了解我的要求的更多解释。您的回答很好,但我需要更优雅的方式将该值发送到 bash 脚本。
    【解决方案3】:

    这几天一直在思考这个问题,只是想到了一些事情。您可以将其中一个 MATLAB 克隆用作 #!脚本解释器。我的选择是 Octave,就像这样:

    #! /usr/bin/octave -qf
    A=matlab_test('test','matlab');
    printf(A)
    

    printf 将 A 的值放入 STDOUT 中,您可以从那里进行管道传输。

    matteson@mauler[~]$ ./oshelltest
    param1 : test
    param2 : matlab
    hello matlab
    matteson@mauler[~]$ ./oshelltest | grep hello
    hello matlab
    

    现在 Octave 与 MATLAB 不完全相同,但它很接近,也许足以满足您的需求。它还具有免费的优势。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-20
      • 1970-01-01
      • 2018-06-25
      • 2018-07-02
      • 1970-01-01
      • 2022-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多