如何在 bash 脚本中从 matlab 获取返回值



>如果我有这个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 脚本中。

你在问两个问题。 我将回答这两个问题,包括为什么根据您的操作系统(在我的操作系统上绝对不可能),然后就与问题相关的解决方法提供建议。

首先,我在让 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都会创建在 Matlab 关闭时关闭的 shell。 也就是说,Matlab 不能在调用它的 shell 之外设置环境变量。

对于本文中讨论的Windows系统,有一个解决方法,它使用Microsoft中的工具。 这里也提到过。

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

这是一种执行类似于您描述的操作的方法。

我假设使用回声不是你真正想要做的。 相反,我猜您想使用存储在环境变量中的字符串输出,以便在进一步处理 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 $temp1是在setenv创建的子外壳中计算的,temp1 保存分配给它的值。 对 shell 的此调用的结果现在存储在 b 中(a 保持 0 表示成功)。 可以想象,您可以通过系统命令传递您想要在 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

您可以将 grepMe 行从 myresult.out 、管道到 sed,并仅选择所需的输出行部分,然后在脚本的其余部分通过管道传输该行。 我认为你可以达到你想要做的事情

这几天一直在想这个问题,只是想到了一些事情。 您可以将其中一个 MATLAB 克隆用作 #!脚本解释器。 我的选择是八度,如下所示:

#! /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并不完全相同,但它很接近,也许足以满足您的需求。它还具有免费的优点。

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

当我尝试这个时,我发现 Matlab 会用它的开场白写满 stdout,所以我最终做了:

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

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

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

这是满足你第一个需求的一种解决方案(你可以只写入一个普通文件,然后对文件进行分类,但你必须使用&&,所以在 Matlab 完全完成之前你不会看到输出。你遇到的第二个问题 - 在 matlab 中做"A = 结果"并能够在 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);

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

最新更新