Как получить возвращаемое значение из matlab в bash script?

Если у меня есть эта функция matlab

function [result] = matlab_test(param1, param2)

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

result = 'hello matlab';

И я хочу назвать эту функцию matlab в bash script как

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

И я хочу этот вывод

test
matlab
hello matlab

Мое требование здесь - найти, можно ли использовать возвращаемое значение из Matlab в моем bash script, а также передать его по конвейеру. Я хочу, чтобы мое приложение было разделено на небольшие компоненты (файлы) и обменивалось данными по конвейеру/параметрам. Короче говоря, я хочу посмотреть, как далеко я могу переносить Matlab script в мой bash script, чтобы я мог установить свою архитектуру кода.
Если я не могу этого сделать, я просто свяжу часть, в которой мне требуется возвращаемое значение из matlab вместе в matlab script.

Ответ 1

Вы задаете два вопроса. Я отвечу на оба вопроса, в том числе на то, почему второй может быть невозможным в зависимости от вашей операционной системы (и, безусловно, невозможно на моем), затем предложите предложение об зависимом от проблемы обходном пути.

Во-первых, я использую script, как это, когда Matlab взаимодействует с оболочкой.

#!/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

дает результат:

[[email protected] ~]$ ./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
>> >> >> 

Таким образом, две версии переменных среды установки не работают. Это приводит нас к вашему второму вопросу.

Причина отказа "эха" заключается в том, что как system, так и setenv создают оболочки, закрытые при закрытии Matlab. То есть, Matlab не может устанавливать переменные среды вне оболочки, которая его вызывала.

Там обходной путь для систем Windows обсуждался здесь.

Я не верю, что обходной путь для * nix-систем для установки переменных среды из Matlab.

Здесь вы можете сделать что-то похожее на то, что вы описали.

Я предполагаю, что использование эха - это не то, что вы на самом деле хотите сделать. Скорее, я предполагаю, что вы хотите использовать вывод строки, хранящийся в переменной среды, который будет использоваться в дальнейшей работе с командами или скриптами в оболочке. Одним из возможных способов решения проблемы было бы следующее:

#!/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 test 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 - присвоенное ей значение. Результат этого вызова оболочки теперь сохраняется в b (a hold 0 указывает на успех). Вполне возможно, что вы могли бы передать все то, что вы хотели бы сделать в оболочке через системную команду, чтобы она выполнялась в подоболочке. Мы должны были бы узнать больше специфики вашей проблемы, чтобы дать полную оценку этого подхода.

Изменения и последующие действия **********************

Ближайшая вещь для упаковки Matlab и bash, о которой я могу думать, это следующий трюк. Вы можете вывести вывод из Matlab script в myresult.out со следующим:

#!/bin/sh 

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

Вы можете выполнить grep строку grepMe от myresult.out, pipe to sed и выбрать только часть нужной строки, а затем передать ее на оставшуюся часть вашего script. Это как можно ближе к тому, что вы пытаетесь сделать.

Ответ 2

Есть две вещи, которые вы пытаетесь сделать здесь. Во-первых: отображение вывода программы 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 был полностью закончен.). Второй вопрос, который у вас есть - выполнение "A = результата" в Matlab и возможность "эха $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);

но я действительно не знаю, как хорошо это сработает.

Ответ 3

Думал об этом в течение последних нескольких дней и просто думал о чем-то. Вы можете использовать один из клонов MATLAB как #! script переводчик. Мой выбор в этом - Octave, вот так:

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

printf ставит значение A в STDOUT и вы можете оттуда оттуда.

[email protected][~]$ ./oshelltest
param1 : test
param2 : matlab
hello matlab
[email protected][~]$ ./oshelltest | grep hello
hello matlab

Теперь Octave не совсем то же самое, что и MATLAB, но он закрывается, может быть, достаточно для ваших нужд. Это также имеет то преимущество, что вы свободны.