2012-03-08 74 views
0

我正在使用的模拟程序需要基于文本的输入文件。我需要通过更改文本文件中的值来以不同配置运行模拟。我正在寻找一种方法来使用任何不需要第三方编译器的脚本自动执行此操作。它必须在Windows XP机器上本地运行。我在MATLAB和FORTRAN中只有一点编码经验。Windows原生脚本根据行号和列号更改文本文件

我将描述我的脚本应该在一些伪代码做些什么的想法:

% speed.txt - a txt file with 10 different speed values 
% coeff.txt - a txt file with 10 different coefficients 
% dist.txt - a txt file with 5 different distance values 
% input.txt - the txt file containing the input parameters. This file has to be changed. 
% output.txt- the output of the simulation 
% sp - the i-th speed value 
% co - the i-th coeff value 
% di - the j-th distance value 
% D:\FO - Final Output folder 

Read input.txt 
for i = 1:10 
    Display i on screen % so I know how much of the batch is done 
    Go to line 37, overwrite 1st four characters with i-th value from speed.txt 
    Go to line 68, overwrite 1st eight characters with i-th value from coeff.txt 
    for j = 1:5 
     Display j on screen % so I know how much of the batch is done 
     Go to line 67, overwrite 1st five characters with j-th value from dist.txt 
     Run simulation.exe 
     When simulation is done, get output.txt, rename it to "output_sp_co_di.txt" 
     and move the file to D:\FO 
    end 
end 

我希望这是可能的一个.bat或.vbs脚本(或其他任何将本机运行)。所有的帮助非常感谢。


编辑:经过一些建议,我开始一个VBS脚本。我从来没有使用过这种语言,但是从废料拉到这里的东西一起下在互联网上:

Option Explicit 

Dim objFSO, strTextFile, strData, strLine, arrLines 
Dim filesys, filetxt, path 
Dim speed(10), ct(10), dist(4), text(73), d(4) 
Dim i, j, k 
i = 0 
j = 0 
k = 0 

speed(0) = 3.0 
speed(1) = 5.0 
speed(2) = 7.0 
speed(3) = 9.0 
speed(4) = 11.0 
speed(5) = 13.0 
speed(6) = 15.0 
speed(7) = 17.0 
speed(8) = 19.0 
speed(9)= 21.0 
speed(10)= 22.0 

ct(0) = 0.987433 
ct(1) = 0.816257 
ct(2) = 0.816361 
ct(3) = 0.720357 
ct(4) = 0.418192 
ct(5) = 0.239146 
ct(6) = 0.154534 
ct(7) = 0.107608 
ct(8) = 0.079057 
ct(9)= 0.060437 
ct(10)= 0.053465 

dist(0) = 173.48 
dist(1) = 260.22 
dist(2) = 346.96 
dist(3) = 433.7 
dist(4) = 520.44 

d(0) = 2 
d(1) = 3 
d(2) = 4 
d(3) = 5 
d(4) = 6 


CONST ForReading = 1 

'name of the text file 
strTextFile = "TurbSim.inp" 

'Create a File System Object 
Set objFSO = CreateObject("Scripting.FileSystemObject") 


'Open the text file - strData now contains the whole file 
strData = objFSO.OpenTextFile(strTextFile,ForReading).ReadAll 

'Split the text file into lines 
arrLines = Split(strData,vbCrLf) 

'Step through the lines 
For Each strLine in arrLines 
    text(i) = strLine 
    i = i + 1 
Next 

'Open text file to write to 
path = objFSO.GetAbsolutePathName("D:\Sandbox\TurbSim.inp") 

For i = 0 To 10 
    If i = 0 Then 
     text(37) = Replace(text(37),"UUUU",speed(i)) 
     text(68) = Replace(text(68),"CCCCCCCC",ct(i)) 
    Else 
     text(37) = Replace(text(37),speed(i-1),speed(i)) 
     text(68) = Replace(text(68),ct(i-1),ct(i)) 
    End If 
    For j = 0 To 4 
     If j = 0 Then 
      text(67) = Replace(text(67),"DDDDD",dist(j)) 
     Else 
      text(67) = Replace(text(67),dist(j-1),dist(j)) 
     End If 

     Set filetxt = objFSO.opentextfile("D:\Sandbox\TurbSim.inp", 2, True) 
     For k = 0 To 73 
      if k = 73 Then 
       filetxt.write text(k) 
      Else 
       filetxt.write text(k) & vbCr & vbLf 
      End If 
      objFSO.CopyFile "D:\Sandbox\TurbSim.inp", _ 
      "D:\Sandbox\input\TurbSim_" & speed(i) & "_" & d(j) &"D.inp" 
     Next 
     filetxt.close 
    Next 
Next  


' wscript.echo text(37) 
' wscript.echo text(68) 
' wscript.echo text(67) 

filetxt.Close 
'Cleanup 
' Set filesys = Nothing 
Set objFSO = Nothing 

问题是,现在的距离部分(j-循环)工作不正常。从生成的输出(TurbSim_speed_dD.inp)我看到只有最后一个距离(520.44)被使用。我不明白为什么,我会在稍后看看。如果任何人有改进的建议,那么你总是受欢迎的想法。

+0

为什么你不开始写一个批处理文件?用'for/L %% i替换伪'for i = 1:10'(1,1,10)do(' – jeb 2012-03-08 07:32:33

+0

我没有开始批处理文件,因为我不知道它是否有能力做我的同事给了我使用vbs文件的建议,因为它们更加灵活,我在某个地方,但是有一些问题我会在后面发布。 – 2012-03-08 09:34:27

回答

0

我已经成功地将各种互联网参考文献中的.vbs脚本放在一起,这些脚本都是我想要的。脚本执行以下操作:

  1. 读入原始输入文件
  2. 存储所述数据线通过线文本阵列
  3. 在速度,系数和距离数据读取从文本文件
  4. 将该数据存储在以单独的速度,系数和距离阵列逐行。
  5. 第一次输入速度和coeff。阵列和 文本阵列中的适当的地方将其写
  6. 循环通过距离阵列和由线写入文本阵列线回到一个.INP文件
  7. 运行于所编辑的输入文件
  8. 等待直到模拟仿真终止。
  9. 将输出文件从当前目录复制到输出文件夹,并在进程中重命名它们。
  10. 等待10秒钟以确保复印完成 10.用所有其他速度和coeff条目重复步骤6-10。这个脚本阵列

要求的工作:

A.与具有“UUUU”的.INP文件的输入文件夹,“DDDDD”,“CCCCCCCC”写在地方,分别是速度,距离并写出系数。

B.输出文件夹

C.这些文件speed.txt,ct.txt和包含速度,系数和距离值distance.txt使用。 D.您应该从管理员帐户运行此脚本。否则,您无权检查仿真是否仍在使用“Win32_process”运行。

Option Explicit 

Dim objFSO, strTextFile, strTData, strLine, arrTLines 
Dim strVelFile, strCtFile, strDistFile 
Dim strVData, strCData, strDData 
Dim arrVLines, arrCLines, arrDLines 
Dim strLineV, strLineC, strLineD 
Dim strComputer, oWMI, colEvents, oEvent 
Dim filesys, filetxt, path, curPath 
Dim speed(), ct(), dist(), text(73) 
Dim oShell 
Dim i, j, k 
i = 0 
j = 0 
k = 0 

' Subroutine to start an executable 
Sub Run(ByVal sFile) 
Dim shell 

    Set shell = CreateObject("WScript.Shell") 
    shell.Run Chr(34) & sFile & Chr(34), 1, false 
    Set shell = Nothing 
End Sub 

CONST ForReading = 1 

' Create a File System Object 
Set objFSO = CreateObject("Scripting.FileSystemObject") 

' Create Shell object. Needed to change directories 
Set oShell = CreateObject("WScript.Shell") 

'Change current directory to \input folder 
oShell.CurrentDirectory = ".\input" 

' The name of the original input file 
' with the UUUU, DDDDD, CCCCCCC in the correct places 
strTextFile = "TurbSim.inp" 

' Open the text file and read it all into strTData 
strTData = objFSO.OpenTextFile(strTextFile,ForReading).ReadAll 

' Go back to parent folder as there all the other .txt files reside 
Set oShell = CreateObject("WScript.Shell") 
oShell.CurrentDirectory = ".\.." 

' name of other input text files 
strVelFile = "speed.txt" 
strCtFile = "ct.txt" 
strDistFile = "dist.txt" 

' Open the text file - str*Data now contains the whole file 
strVData = objFSO.OpenTextFile(strVelFile,ForReading).ReadAll 
strCData = objFSO.OpenTextFile(strCtFile,ForReading).ReadAll 
strDData = objFSO.OpenTextFile(strDistFile,ForReading).ReadAll 

' Split the text files into lines 
arrTLines = Split(strTData,vbCrLf) 
arrVLines = Split(strVData,vbCrLf) 
arrCLines = Split(strCData,vbCrLf) 
arrDLines = Split(strDData,vbCrLf) 

' Give the speed, ct and dist arrays their dimension 
ReDim speed(UBound(arrVLines)) 
ReDim ct(UBound(arrCLines)) 
ReDim dist(UBound(arrDLines)) 

' Add data to arrays text, speed, ct and dist line by line 
For Each strLine in arrTLines 
    text(i) = strLine 
    i = i + 1 
Next 

'Reset counter 
i = 0 

' Step through the lines speed 
For Each strLineV in arrVLines 
    speed(i) = strLineV 
    i = i + 1 
Next 
i = 0 
' Step through the lines ct 
For Each strLineC in arrCLines 
    ct(i) = strLineC 
    i = i + 1 
Next 
i = 0 
' Step through the lines dist 
For Each strLineD in arrDLines 
    dist(i) = strLineD 
    i = i + 1 
Next 
i = 0 

' Get the current path. Needed to point to the executable. 
curPath = objFSO.GetAbsolutePathName(".") 

For i = 0 To UBound(speed) 
    If i = 0 Then 
     ' Replace the UUUU and CCCCCCCC values 
     ' Only the first run.  
     text(37) = Replace(text(37),"UUUU",speed(i)) 
     text(68) = Replace(text(68),"CCCCCCCC",ct(i)) 
    Else ' Replace the previous speed and coeff. values with the current one 
     text(37) = Replace(text(37),speed(i-1),speed(i)) 
     text(68) = Replace(text(68),ct(i-1),ct(i)) 
    End If 
    For j = 0 To UBound(dist) 
     If j = 0 And i = 0 Then 
      ' Replace the DDDDD value (only at first run) 
      text(67) = Replace(text(67),"DDDDD",dist(j)) 
     ElseIf j = 0 And i > 0 Then 
      ' Replace the distance value of the previous speed/coeff. case 
      ' with the current one 
      text(67) = Replace(text(67), dist(UBound(dist)), dist(j)) 
     Else ' Replace the previous distance value with the current one 
      text(67) = Replace(text(67),dist(j-1),dist(j)) 
     End If 
     Set filetxt = objFSO.opentextfile(curPath & "\TurbSim.inp", 2, True) 
     For k = 0 To 73 ' Write to an .inp file line by line 
      if k = 73 Then ' Prevent adding a new line at the end 
       filetxt.write text(k) 
      Else 
       filetxt.write text(k) & vbCr & vbLf 
      End If 
     Next 
     filetxt.close 
     ' Execute the simulation 
     Run curPath &"\TurbSimGW.exe" 

     strComputer = "." 
     Set oWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") 

     '# Create an event query to be notified within 3 seconds when TurbSimGW is closed 
     Set colEvents = oWMI.ExecNotificationQuery _ 
      ("SELECT * FROM __InstanceDeletionEvent WITHIN 3 " _ 
      & "WHERE TargetInstance ISA 'Win32_Process' " _ 
      & "AND TargetInstance.Name = 'TurbSimGW.exe'") 

     '# Wait until TurbSimGW is closed 
     Set oEvent = colEvents.NextEvent 

     ' Copy and rename output files 
     objFSO.CopyFile curPath & "\TurbSim.wnd", _ 
     curPath & "\output\TurbSim_" & speed(i) & "_" & j+2 &"D.wnd" 
     wscript.sleep 10000 ' time to allow copying the files 
    Next 
Next  


'' ' wscript.echo text(37) 
'' ' wscript.echo text(68) 
'' ' wscript.echo text(67) 

filetxt.Close 
' Cleanup 
' Set filesys = Nothing 
Set objFSO = Nothing 

现在它的工作完美无瑕。然而,要求D的解决方案会很好。我的解决方法是,而不是检查程序是否被终止,我只是设置一个睡眠值。对于这个睡眠值,我知道模拟已经完成,输出文件已准备好复制。

+0

在一个批处理文件中,任何命令的执行都会实现,直到前一个命令结束为止,所以这个检查甚至不需要:) – Aacini 2012-03-10 04:00:25

2

下面的批处理文件是您的VBS脚本的蝙蝠版本:

@echo off 
SetLocal EnableDelayedExpansion 

REM Auxiliary macro for easier replacements 
set Replace=for /F "tokens=1,2 delims==" %%x in 

:: speed - vector with 11 different speed values 
Set i=0 
For %%s in (3.0 5.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0 21.0 22.0) do (
    Set speed[!i!]=%%s 
    Set /A i+=1 
) 

:: ct - vector with 11 different coefficients 
Set i=0 
For %%c in (0.987433 0.816257 0.816361 0.720357 0.418192 0.239146 0.154534 0.107608 0.079057 0.060437 0.053465) do (
    Set ct[!i!]=%%c 
    Set /A i+=1 
) 

:: dist - vector with 5 different distance values 
Set i=0 
For %%d in (173.48 260.22 346.96 433.7 520.44) do (
    Set dist[!i!]=%%d 
    Set /A i+=1 
) 

REM d does not need to be a vector because d(i) = i+2 

:: Split the text file into lines, and Step through the lines 
Set i=0 
For /F "delims=" %%l in (TurbSim.inp) do (
    Set "text[!i!]=%%l" 
    Set /A i=i+1 
) 

For /L %%i in (0,1,10) do (
    If %%i == 0 (
     %Replace% ("UUUU=!speed[%%i]!") do set "text[37]=!text[37]:%%x=%%y!" 
     %Replace% ("CCCCCCCC=!ct[%%i]!") do set "text[68]=!text[68]:%%x=%%y!" 
    ) Else (
     set /A iM1=i-1 
     %Replace% ("!iM1!") do set speed_iM1=!speed[%%x]!& set ct_iM1=!ct[%%x]! 
     %Replace% ("!speed_iM1!=!speed[%%i]!") do set "text[37]=!text[37]:%%x=%%y!" 
     %Replace% ("!ct_iM1!=!ct[%%i]!") do set "text[68]=!text[68]:%%x=%%y!" 
    ) 
    For /L %%j in (0,1,4) do (
     If %%j == 0 (
      %Replace% ("DDDDD=!dist[%%j]!") do set "text[67]=!text[67]:%%x=%%y!" 
     ) Else (
      set /A jM1=j-1 
      %Replace% ("!jM1!") do set dist_jM1=!dist[%%x]! 
      %Replace% ("!dist_jM1!=!dist[%%j]!") do set "text[67]=!text[67]:%%x=%%y!" 
     ) 
     set /A d=j+2 
     (For /L %%k in (0,1,73) do (
      if %%k == 73 (
       set /P =!text[%%k]!< NUL 
      ) Else (
       echo !text[%%k]! 
      ) 
     )) > "D:\Sandbox\input\TurbSim_!speed[%%i]!_!d!D.inp" 
    ) 
) 


echo %text[37]% 
echo %text[68]% 
echo %text[67]% 

注:

1 - 这是基于你的vbs脚本第一次尝试批处理文件;我真的不明白你想要做什么,只是做了一个直接的翻译。看来您在问题中提出的要求与vbs脚本不同。如果你给我具体的细节,任何问题都可以解决。

2-上一个批处理文件从输入文件中删除任何空行。如有需要可以解决这个问题。

3-批量文本替换为文本,不是数值。任何数字必须写作完全相同的作为数组值以便被替换。我认为同样的行为适用于vbs。

4-输入文件不能包含某些特殊的批处理字符,如! ^和其他人。这可能只在某些情况下得到解决。

+0

非常感谢你的努力,但只是几分钟以前我设法让我的vbs文件工作,我会在这里发布以供进一步参考 – 2012-03-09 05:52:09

+0

经过一段时间的思考,我现在明白了为什么你不明白我想要做什么,我首先发布的vbs代码不会做我要求的最初是因为它只是一个部分代码,我还没有完成它,当我离开我的工作时,我在这里发布它来表明我正在处理它,我发布的部分只是输入文件修改。我已经发布了完整的vbs代码,按照我在第一篇文章中的要求工作。谢谢y ou再次为你的努力和遗憾,我给了不清楚的信息。 – 2012-03-09 06:39:41