2016-12-21 6 views
0

Мне нужно построить несколько файлов в одном сюжете с помощью скрипта bash. Я могу справиться с этим, заявив, расположение файлов вручную в функции участка т.е.gnuplot печать нескольких файлов с массивом

plot "$outputdir/10/values.csv" using 1:2 with lines title "10", \ 
"$outputdir/20/values.csv" using 1:2 with lines title "20", \ 
"$outputdir/30/values.csv" using 1:2 with lines title "30" 

это будет печатать все три значения файлов на одном участке. Но у меня есть динамический массив, который изменяется в зависимости от того, сколько значений он должен получить. Так позволяет сказать, обр массив выглядит следующим образом вместо

arr=(10 20 30 40) 
#Sometimes arr has more values ex; arr=(10 20 30 40 50 60 70 80) 
#arr corresponds to folders that will be created 
#And will contain a values.csv file that I want to plot 

Тогда 40/values.csv не будет печататься, если я не вручную изменить код участка

Моя текущая попытка исправить это цикл в Gnuplot

#The array arr is dynamically generated in another function 
#Varies in size as example above 

ArrLength=${#arr[@]} #Get the length of array 
plot for [p=0:$ArrLength] "$outputdir/${arr[$p]}/values.csv" using 1:2 with lines title "${arr[$p]}" 

Я не получаю ошибку при построении, но в сюжет строится только одно значение и то первое значение в массиве т.е. только участок $ OutputDir/10/values.csv.

Я попытался установить p = 0: 4, чтобы построить первые пять файлов, и все же он отобразил только первый файл. Что не так с циклом for выше?

С наилучшими пожеланиями

ответ

2

Вы, кажется, смешивания Баш и GNUPLOT странным образом. Использование сценария bash для создания сценария gnuplot «на лету» со вставленными переменными - это быстрый способ запутать себя. Это также затрудняет чтение и отладки. Легко забыть, что оценивает bash и оценивает gnuplot.

Когда я смотрю на Вашей первой линии

ArrLength=${#arr[@]} #Get the length of array 

Я могу видеть, что это Баш код, потому что Gnuplot интерпретирует комментарий, начиная с первого #. (Это также синтаксис bash для массивов, а не gnuplot.) Знак доллара $ имеет другое значение в gnuplot. Вместо отметки идентификатора переменной $ является оператором номера столбца ($2 - столбец 2, $i - столбец i и т. Д.). Так что смотрите на линии

plot for [p=0:$ArrLength] "$outputdir/${arr[$p]}/values.csv" using 1:2 with lines title "${arr[$p]}" 

Это явно линия Баш синтаксиса, по-видимому, внутри строки, пытаясь записать строку Gnuplot. Bash будет оценивать переменные $ArrLength, $outputdir и ${arr[$p]} и заменять их некоторой строкой своих значений. Также имейте в виду, что p является переменной в gnuplot, а не переменной в bash. Баш будет оценивать $p до что-то (пустая строка, если она не определена). Вы не можете ожидать, что переменная gnuplot p будет использоваться как индекс в оценке bash ${arr[$p]}, а затем каким-то образом приведет к другой строке для каждой итерации цикла gnuplot.

Короче говоря, то, что вы написали, не является синтаксисом gnuplot, и это действительно не минимальный и полный сценарий bash. Не совсем ясно, как вы намеревались использовать bash и gnuplot так, чтобы они соответствовали друг другу, но, похоже, вы слишком тесно связаны с ними.


Мое предложение написать Баш скрипт а и написать GNUPLOT скрипт в (в виде отдельных файлов). Gnuplot имеет собственный контроль потока, петли итерации и переменную оценку. Вы можете написать автономный скрипт gnuplot для общего случая всего, что вам нужно для этого, а затем указать его в командной строке из вашего сценария bash.

Например, кажется, что ваши подкаталоги все кратные 10, и всегда начиная с 10. Единственный переменный аспект - это то, сколько из них (что последнее). Скажем, это последнее значение было каким-то образом сохранено в переменной gnuplot last. Кроме того, предположим, что мы каким-то образом имеют базовый каталог вывода в outputdir:

(Внутри GNUPLOT сценарий, названный plot.gp):

plot for [p=10:last:10] sprintf("%s/%d/values.csv", outputdir, p) with lines title sprintf("%d", p) 

for [p=10:last:10] означает итерацию от 10 до last (включительно), добавив 10 на каждой итерации. Первая функция sprintf() (например, C) строит строку с outputdir и p (обе являются переменными в gnuplot). using 1:2 не требуется, поскольку первые два столбца являются столбцами по умолчанию для использования with lines, но вы можете включить их, если хотите быть явным. Второй sprintf() строит строку заголовка из переменной итерации p.

Теперь предполагается, что outputdir и last имеют значащие значения. Вы можете присвоить эти значения из вашего Баш скрипт при вызове Gnuplot в командной строке:

(Внутри Баш сценария , вызовите Gnuplot скрипт)

gnuplot -e "last=40" -e "outputdir=\"$outputdir\"" plot.gp 

Опция -e рассказывает GNUPLOT к оцените данную строку перед запуском скрипта в файле plot.gp. В этом примере переменная gnuplot last будет иметь значение 40, а переменная gnuplot outputdir будет иметь любое значение bash, оценивающее $outputdir. Обратите внимание на скрытые двойные кавычки в двойных кавычках. Внешние двойные кавычки должны позволить bash оценивать переменные внутри строки ($outputdir необходимо оценить bash). Внутренние (экранированные) кавычки должны ограничивать строку в коде gnuplot. Например, если bash оценивает $outputdir до data, тогда gnuplot увидит outputdir="data", который является допустимым назначением gnuplot строки переменной outputdir. Вы можете, если вы хотите, объединить эти два варианта -e в один:

gnuplot -e "last=40;outputdir=\"$outputdir\"" plot.gp 

Вы, вероятно, хотите использовать значение last из вашего массива в Баш, а не жесткого кодирования это так. Поэтому на практике это может быть больше похоже на

gnuplot -e "last=${arr[${#arr[@]}-1]};outputdir=\"$outputdir\"" plot.gp 

Или, если у вас есть bash 4.3 или более поздняя версия, вы должны быть в состоянии использовать negative index:

gnuplot -e "last=${arr[-1]};outputdir=\"$outputdir\"" plot.gp 

Обратите внимание, что нет спаслись кавычки вокруг использования переменного массива. Ожидается, что он будет оценивать целое число (40, 90 и т. Д.), И мы хотим назначить last целому числу, а не строке, например outputdir.

Если эта строка кажется сложной, попробуйте подумать обо всем скрипте, подобном этому. Было бы легко запутаться в том, что делает bash и что делает gnuplot.

В целом, напишите сценарий bash и отдельный скрипт gnuplot. Gnuplot способен обрабатывать общий случай. Из bash просто дайте ему некоторые особенности «на лету», не пытайтесь генерировать весь скрипт «на лету». Это действительно упрощает работу.

+0

Не знал, что gnuplot не будет принимать синтаксис bash в сценарии bash. Мне придется переосмыслить это. Спасибо за подробное объяснение. – S4M11R