使用批处理文件生成多个Mathematica脚本



希望这不是一个重复的问题;我搜索过没有太多结果(大部分是不知道要搜索的词)。

我目前有一个mathematica脚本,它打开一个数据文件并在上面运行一系列命令。在该脚本中,我必须编辑每个数据文件的某些值,例如analysis_20_70.m可能会读作:

(* ::Package:: *)
Clear[NN, TxyzAll, q, Txyz, twospace, dps, threespace, threeclosed, plane]
datChoice = ReadList[
"/n/homeserver2/user2a/scallion/mathematica/20_70.dat", {Number, Number, Number}]; 
NN = 51; 
% LOTS OF CODE HERE
Export[
"/n/homeserver2/user2a/scallion/mathematica/20_70_time.txt", 
time]; 
Exit[]

因此,为我想要运行的每个文件编辑它是低效的。一般来说,我对脚本是新手,但我认为我可以使用批脚本来自动化这个过程(即脚本1读取20_70.dat,NN=51,脚本2读取20_75.dat,NN=56,脚本3读取20_80.dat、NN=61等)

到目前为止,我已经拼凑出了这样的东西:

@echo off
set "begin=20"
set "end=150"
set "count=70"
:LOOP
if %count% GTR %end% (goto END)
(
echo (* ::Package:: *)
echo Clear[NN, TxyzAll, q, Txyz, twospace, dps, threespace, threeclosed, plane]
echo datChoice = ReadList[
echo     "/n/homeserver2/user2a/scallion/mathematica/20_70.dat", {Number, Number, Number}]; 
echo NN = 51; 
echo Exit[]
) > testfile_%begin%.txt
set /a count+=5
goto LOOP
:END

(理想情况下,20_70.dat会变成类似%begin%_%count%.dat的内容)。

如果我用一些简单的东西代替中间部分,比如echo-helloworld>testfile_%begin%.txt,我就没有问题了。然而,试图打印整个mathematica脚本似乎很混乱,我不知道结果文件中是否会出现换行问题/隐藏字符。因此,我的问题:

1) 。有没有比在每行前面放回显更好的方法来打印多行?如果是的话,我会保留用计数器更改文件名的能力吗?

2) 。我的代码自然有()[];=和其他保留字符,所以我似乎必须要么把每一行都放在引号中(在这种情况下,我不能删除引号),要么手动转义每一个违规行为。我可以去做,但我想知道是否有更好的方法。

3) 。批处理文件可能不是解决问题的方法。如果有其他方法可以解决这个问题,我愿意尝试任何方法。

感谢大家的帮助!

1)命令echo将脚本内容中的文本打印到文件中(当然包括stdout)。我还建议使用type,它可以从另一个文件复制文本,在这种情况下,您不必考虑特殊字符。所以我会写这样的东西:

type static_begin.txt > output.txt
echo A %dynamic% part >> output.txt
type static_end.txt >> output.txt

它只是复制静态的(不变的)开始和结束,并允许在它们之间放置不同的东西。运算符>>表示追加到文件末尾。

2) 可以使用^转义批处理文件的特殊字符,例如^(

@ECHO OFF
SETLOCAL
SET "sourcedir=c:sourcedir"
SET "destdir=c:destdir"
SET "skeleton=%~1"
SET /a count=0
FOR /f "usebackqdelims=" %%S IN ("%~2") DO (
CALL :genscript %%S
)
GOTO :EOF
:genscript
:: remove variables starting $
FOR  /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
SET /a paramcount=1
:paramloop
SET "$%paramcount%=%1"
IF DEFINED $%paramcount% SET /a paramcount+=1&shift&GOTO paramloop
SET /a paramcount -=1
:: Now have $1=1st param, $2=second, etc.
:: Simple substitution : only 2 parameters (dat and NN)
IF DEFINED $3 GOTO loopy
CALL :genfile %$1% %$2%
GOTO :eof
:: We have more than two parameters in the data line.
:: Let's define params as %1=start, %2=incr, %3=end for first item
:: %4=start, %5=incr, %6=end for second item
:: %7=start, %8=incr, %9=end for third item
:: how it's done - up to the user
:loopy
FOR /L %%a IN (%$1% %$2% %$3%) DO (
FOR /L %%b IN (%$4% %$5% %$6%) DO (
FOR /L %%c IN (%$7% %$8% %$9%) DO (
CALL :genfile %%a_%%b %%c
)
)
)
GOTO :eof
:genfile
SET "$batchline1=    "/n/homeserver2/user2a/scallion/mathematica/%1.dat", {Number, Number, Number}];"
SET "$batchline2=NN = %2;"
SET "$batchline3=   "/n/homeserver2/user2a/scallion/mathematica/%1_time.txt","
SET /a count+=1
SET outscript=script%count%.m
(
FOR /f "tokens=1*delims=:" %%L IN ('FINDSTR /n /r "$" "%skeleton%"') DO (
SET "line=%%M"
CALL :subs
IF DEFINED line ECHO(%%M
)
)>"%destdir%%outscript%"
GOTO :eof
:: Do the substitution
:subs
:: if LINE is not defined, empty line
IF NOT DEFINED line SET line=Y&GOTO :EOF
SET "line=%line:"=%"
SET "line=%line:&=%"
SET "line=%line:)=%"
SET "line=%line:(=%"
FOR /f "tokens=1*delims==" %%s IN ('set $batch') DO IF "%%s"=="$%line%" (
SET "line="
ECHO(%%t
GOTO :eof
)
GOTO :eof

我相信这会奏效。

将其作为thisbatch skeleton.txt controlfile.txt运行

其中skeleton.txt是

(* ::Package:: *)
Clear[NN, TxyzAll, q, Txyz, twospace, dps, threespace, threeclosed, plane]
datChoice = ReadList[
batchline1
batchline2
% LOTS OF CODE HERE
Export[
batchline3
time]; 
Exit[]

也就是说,您的原始.m文件,其中的变量行被batchline1..3替换,并且这些行被脚本构建和替换。

controlfile.txt是

20_70 51
20 1 22 70 2 74 51 5 66

它将从骨架构建脚本,从策略上替换20_7051,然后,仅仅因为它有可能(在不了解您的情况的情况下)为(20 to 22 step 1)_(70 to 74 step 2)(51 to 66 step 5)的所有组合类似地构建脚本

似乎对我有用…

最新更新