Разбор строки с использованием пакетного скрипта

4686
Mihir

Как я могу разобрать строку, используя пакетный скрипт?

Цель состоит в том, чтобы сохранить в массиве все, что находится под, Import:и удалить, #headнапример, -> //MPackages/Project/config/abc.txtи //Packages/Project/config/cde.txt.

test.txt:

Version: 4.5.0 Import: //MPackages/Project/config/abc.txt #head //Packages/Project/config/cde.txt #head View: //MPackages/Project/config/ac.txt #head //Packages/Project/config/de.txt #head 

Моя попытка:

@echo off  set buildlog="devel.p4inc"  setlocal EnableDelayedExpansion for /F "tokens=*" %%A in (devel.p4inc) do ( if /i "%%A"=="Import:" set "import=true" IF DEFINED import (echo %%A) ) 

желаемый результат

 //MPackages/Project/config/abc.txt  //Packages/Project/config/cde.txt 

что-нибудь под Импорт:

2
Ради ясности, что не так с тем, что вы пробовали? Какие результаты вы получите с этим (правильно или неправильно)? Ƭᴇcʜιᴇ007 9 лет назад 0
результат был неправильным .. он печатает все под Import: .. мне бы хотелось распечатать только //MPackages/Project/config/abc.txt и //Packages/Project/config/cde.txt .. Mihir 9 лет назад 0
Добавьте результат, который вы хотите получить STTR 9 лет назад 0
добавлено в исходный вопрос Mihir 9 лет назад 0

3 ответа на вопрос

1
Ƭᴇcʜιᴇ007

One of the main problems in your logic is that you set the "import" variable once if something is true, but never reset it, or undefined it if it's not true anymore. So after the first time it's set, it will remain "defined" for the rest of the loop.

My preference is to set the variable specifically (true or false). Set it to false to start, then set it to true as wanted, but then also ensure you set it back to false when you need to. Then, at each iteration of the loop check if the variable is specifically set to True or False instead of checking if it's just defined.

This code works for me based on your info/goals:

@echo off setlocal EnableDelayedExpansion set buildlog=test.txt set import=false for /F "tokens=*" %%A in (%buildlog%) do ( if /i "%%A"=="Import:" ( set import=true ) if /i "%%A"=="View:" ( set import=false ) if !import!==true ( if not "%%A"=="Import:" ( for /F "tokens=1" %%B in ("%%A") do ( echo %%B ) ) ) ) 

We purposefully set the "Import" variable (flag) to false to start.

First For-loop goes through each line in the file (test.txt in this example, as specified by the "buildlog" variable; note: you need to remove the quotes around the file name in the variable for it to work in the For-loop).

The first IF sees if the current line is the "Import:" line, and if so, it flips the "import" flag to true.

The next IF sees if the current line is the "View:" line, and if so, it flips the "import" flag (back to) to false, so that it stops processing each line.

The 3rd IF checks if that "import" flag is true, and if so, it processes the line.

If it's true then the nested (4th) IF then checks if the line is the actual "import:" line, and if not, displays the line (keeps it from showing the "Import:" line in the output).

The second For-loop goes through the line we want displayed, and pulls only the first Token set which is (just) the path you want, leaving off the #head.

More/related info:

Edit after comments:

To deal with the "View:" line if it has a version number after it you could modify the code to something like:

@echo off setlocal EnableDelayedExpansion set buildlog=test.txt set import=false for /F "tokens=*" %%A in (%buildlog%) do ( for /F "tokens=1" %%B in ("%%A") do ( if /i "%%B"=="Import:" ( set import=true ) if /i "%%B"=="View:" ( set import=false ) if !import!==true ( if not "%%B"=="Import:" ( for /F "tokens=1" %%C in ("%%A") do ( echo %%C ) ) ) ) ) 

This added For-loop will pull the first token off the line to check if it's "View:" or "Import:" instead of checking the whole line. Effectively ignoring anything after the first space it encounters on the line to do the check.

Черт .. ты замечательный .. хорошее объяснение .. он удаляет #head и но печатает все View: и вещи в views .. if / i "%% A" == "View:" (set import = false ) не работает.. Mihir 9 лет назад 0
Не уверен, что вам сказать, это работает здесь на основе ваших данных примера. Вы уверены, что строка в ваших реальных данных на самом деле просто "View:", и нет никаких лишних пробелов или чего-то еще? Соответствует ли заглавная буква и т. Д.? Можете ли вы предоставить копию фактического файла данных, с которым вы его запускаете? Ƭᴇcʜιᴇ007 9 лет назад 0
извините, на самом деле я запускаю любое приложение, где view выглядит как "View: 3.2.43" Mihir 9 лет назад 0
Ах, хорошо, я выложу модифицированную версию, которая занимается этим ... Ƭᴇcʜιᴇ007 9 лет назад 0
Спасибо TECHIE007 за вашу помощь и отличное объяснение ... Mihir 9 лет назад 0
1
kingpin
@echo off for /F "usebackq tokens=1" %%A in ("devel.p4inc") do ( Set temp=False if "%%A" == "View:" Goto Exit if not "%%A" == "Import:" if not "%%A" == "Version:" echo %%A ) :Exit 
Не могли бы вы также объяснить это @kingpin? Это сделает ваш ответ более полезным для будущих посетителей, если вы это сделаете :) Вы можете [отредактировать] ответ, чтобы добавить пояснения :) ᔕᖺᘎᕊ 9 лет назад 1
0
STTR

command-line:

powershell [string]$f=gc test.txt;$pL=$f.IndexOf('Import:')+7;$pR=$f.IndexOf('View:');$s=$f.Substring($pL,$pR-$pL);$s -split'#head'^|ac result.txt 

powershell:

powershell ./parsefl.ps1 

parsefl.ps1

[string]$f=gc test.txt; $pL=$f.IndexOf('Import:')+'Import:'.Length;$pR=$f.IndexOf('View:'); $s=$f.Substring($pL,$pR-$pL); $s -split'#head'|ac result.txt