Собственный скрипт Windows для изменения текстового файла на основе номера строки и столбца - PullRequest
0 голосов
/ 08 марта 2012

Для программы моделирования, которую я использую, требуется текстовый входной файл.Мне нужно запустить симуляцию в разных конфигурациях, изменив значения в текстовом файле.Я ищу способ сделать это автоматически с любым скриптом, который не требует сторонних компиляторов.Он должен работать на компьютере под управлением 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 ]

2 голосов
/ 09 марта 2012

Пакетный файл ниже представляет собой .bat-версию вашего 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 - это Batch-файл первой попытки на основе вашего VBS-скрипта;Я действительно не понимаю, что вы пытались сделать и просто сделали прямой перевод.Кажется, что требования, которые вы указали в вопросе, не совпадают со сценарием VBS.Любая проблема может быть решена, если вы дадите мне конкретные данные.

2- Предыдущий пакетный файл удалит любую пустую строку из входного файла.Это может быть решено при необходимости.

3- Текстовая замена в Пакете является текстовой , НЕ числовым значением.Любое число должно быть записано точно таким же , что и значения массива для замены.Я думаю, что то же самое поведение относится к VBS.

4 - Входной файл не должен содержать определенные специальные символы пакета, как!^ и другие.Это может быть исправлено только в некоторых случаях.

0 голосов
/ 09 марта 2012

Мне удалось собрать сценарий .vbs из различных ссылок в Интернете, который делает то, что я хочу. Сценарий выполняет следующие действия:

  1. Читает в исходном файле ввода
  2. Сохраняет данные построчно в текстовом массиве
  3. Считывает данные о скорости, коэффициенте и расстоянии из текстового файла
  4. Сохраняет эти данные в отдельных массивах скорости, коэффициента и расстояния строка за строкой.
  5. Принимает первый ввод скорости и коэффициента. массив и записывает его в соответствующих местах в текстовый массив
  6. Прокручивает массив расстояний и записывает текстовый массив построчно обратно в файл .inp
  7. Запускает симуляцию с отредактированным входным файлом
  8. Ожидание завершения симуляции.
  9. Копировать выходные файлы из текущего каталога в выходную папку, переименовывая их в процессе.
  10. Подождите 10 секунд, чтобы убедиться, что копирование завершено 10. Повторите шаги 6-10 со всеми остальными значениями скорости и коэффициента. массив

Требования для работы этого скрипта:

A. Входная папка с INP-файлом, в котором "UUUU", "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 было бы неплохо. Мой обходной путь вместо того, чтобы проверить, завершена ли программа, я просто установил значение сна. Для этого значения сна я точно знаю, что симуляция выполнена, а выходные файлы готовы к копированию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...