Windows本机脚本,用于根据行号和列号更改文本文件

时间:2012-03-08 06:41:13

标签: text batch-file

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

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

% 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)。我真的不明白为什么,我稍后再研究一下。如果有人有改进的建议,那么你的想法永远是受欢迎的。

2 个答案:

答案 0 :(得分:2)

下面的批处理文件是vbs脚本的.bat版本:

@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-批处理中的文本替换是 textual ,而不是数值。任何数字必须与数组值完全相同才能被替换。我认为同样的行为适用于vbs。

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

答案 1 :(得分:0)

我已经成功地从各种互联网引用中提取了一个.vbs脚本,它可以实现我想要的功能。该脚本执行以下操作:

  1. 读入原始输入文件
  2. 在文本数组中逐行存储数据
  3. 从文本文件中读取速度,系数和距离数据
  4. 逐行将这些数据存储在单独的速度,系数和距离数组中。
  5. 首先进入速度和系数。数组并将其写入到的适当位置 文本数组
  6. 循环遍历距离数组并逐行将文本数组写回.inp文件
  7. 使用已编辑的输入文件
  8. 运行模拟
  9. 等待模拟终止。
  10. 将输出文件从当前目录复制到输出文件夹,并在此过程中重命名。
  11. 等待10秒钟以确保复制完成 10.使用speed和coeff的所有其他条目重复步骤6-10。阵列
  12. 此脚本的要求:

    一个。一个带有.inp文件的输入文件夹,其中“UUUU”,“DDDDD”,“CCCCCCCC”写在应分别写入速度,距离和系数的地方。

    B中。输出文件夹

    ℃。文件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要求的解决方案会很好。我的解决方法是检查程序是否终止,而不是检查程序是否设置了睡眠值。对于这个睡眠值,我确信模拟已完成,输出文件已准备好复制。