2017-02-21 13 views
0

У меня есть сценарий, который извлекает строки, такие как:Как вычесть строки и ненулевые значения из txt-файла?

THIS_IS_A_LINE: =

THIS_IS_A_LINE2: =

и выводит все того же вида в другой текстовый файл как:

THIS_IS_A_LINE

THIS_IS_A_LINE2

Сценарий выглядит следующим образом:

set "file=%cd%/Config.mak" 
set /a i=0 
set "regexp=.*:=$" 
setlocal enableDelayedExpansion 
IF EXIST Source_List.txt del /F Source_List.txt 
for /f "usebackq delims=" %%a in ("%file%") do (
    set /a i+=1 
    call set Feature[!i!]=%%a 
) 
cd .. && cd .. 
rem call echo.!Feature[%i%]! 
for /L %%N in (1,1,%i%) do (
    echo(!Feature[%%N]!|findstr /R /C:"%regexp%" >nul && (
     call echo FOUND 
     call set /a j+=1 
     call set Feature_Disabled[%j%]=!Feature[%%N]:~0,-2! 
     call echo.!Feature_Disabled[%j%]!>>Source_List.txt 
    ) || (
     call echo NOT FOUND 
    ) 
) 
endlocal 

У меня также есть еще один сценарий, который извлекает строки, такие как:

THIS_IS_ANOTHER_LINE: = True

THIS_IS_ANOTHER_LINE2: = True ...

и выводит все того же вида в другой файл .txt как:

THIS_IS_ANOTHER_LINE

THIS_IS_ANOTHER_LINE2 ...

Сценарий следующий:

set "file=%cd%/Config.mak" 
set /a i=0 
set "regexp=.*:=true$" 
setlocal enableDelayedExpansion 
IF EXIST Source_List2.txt del /F Source_List2.txt 
for /f "usebackq delims=" %%a in ("%file%") do (
    set /a i+=1 
    call set Feature[!i!]=%%a 
) 
cd .. && cd .. 
rem call echo.!Feature[%i%]! 
for /L %%N in (1,1,%i%) do (
    echo(!Feature[%%N]!|findstr /R /C:"%regexp%" >nul && (
     call echo FOUND 
     call set /a j+=1 
     call set Feature_Disabled[%j%]=!Feature[%%N]:~0,-6! 
     call echo.!Feature_Disabled[%j%]!>>Source_List2.txt 
    ) || (
     call echo NOT FOUND 
    ) 
) 
endlocal 

Тем не менее, есть третий вид линий, которые содержат числовые числа (также некоторые шестнадцатеричные значения), например:

THIS_IS_AN_UNPROCESSED_LINE: = 0xA303

THIS_IS_AN_UNPROCESSED_LINE2: = 1943

THIS_IS_AN_UNPROCESSED_LINE3: = HELLO_DOOD_CAN_YOU_PARSE_ME?

Так мне нужен способ извлечения, а также те виды линий в другой текстовый файл, например:

THIS_IS_AN_UNPROCESSED_LINE: = 0xA303

THIS_IS_AN_UNPROCESSED_LINE2: = 1943

THIS_IS_AN_UNPROCESSED_LINE3: = HELLO_DOOD_CAN_YOU_PARSE_ME?

Поэтому в основном извлечь строки, которые не являются такого рода:

THIS_IS_AN_UNPROCESSED_LINE: =

или

THIS_IS_AN_UNPROCESSED_LINE: = истинный

но держа обе стороны от входа линии.

Я знаю, что должен быть какой-то трюк с регулярным выражением, но я просто не могу его найти.

+0

не спам-теги: python здесь неактуальен. Выбрано –

+0

Пожалуйста, правильно отформатируйте вопрос. – Jan

+1

@Jackson, попробуйте сократить свой вопрос до более читаемой вещи. Я потерял след в середине ... – user2141046

ответ

0

Вы сделали свой код намного сложнее, чем нужно. Нет необходимости создавать массив каждой строки в файле.

Если нет никаких других : или = перед первым :=, то вы можете использовать FINDSTR, чтобы напечатать все строки, содержащие строку, а затем :=. FOR /F может захватывать и анализировать каждую соответствующую строку в частях до и после :=, а затем IF операторы могут классифицировать три разных типа линий.

Я использую n>, чтобы открыть все три выходных файла вне основного блока кода для повышения производительности, а затем я использую синтаксис &n>, чтобы направлять каждый вывод в соответствующий, уже открытый файл. Я использую ручки с большим номером, чтобы избежать проблем, описанных в Why doesn't my stderr redirection end after command finishes? And how do I fix it?.

@echo off 
setlocal 
set "file=Config.mak" 
set /a "empty=7, true=8, unprocessed=9" 
%empty%>empty.txt %true%>true.txt %unprocessed%>unprocessed.txt (
    for /f "delims=:= tokens=1*" %%A in ('findstr /r "^[^:=][^:=]*:=" "%file%"') do (
    if "%%B" equ "" (
     >&%empty% (echo %%A) 
    ) else if "%%B" equ "true" (
     >&%true% (echo %%A) 
    ) else (
     >&%unprocessed% (echo %%A:=%%B) 
    ) 
) 
) 

выше будет игнорировать строки, которые содержат : или = перед тем :=, и он не будет работать должным образом, если первый символ после := является : или =. Я предполагаю, что это не проблема.

Должно быть относительно легко написать очень эффективное решение с использованием PowerShell, VBScript или JScript, что устраняет ограничения.

Вы также можете использовать JREPL.BAT - a powerful and efficient regular expression text processing command line utility. JREPL.BAT - это чистый скрипт (гибридный пакет/JScrpt), который запускается изначально на любом компьютере с Windows XP, и не требуется сторонний exe. И JREPL намного быстрее, чем любое чистое пакетное решение, особенно если файлы большие.

Вот один JREPL решение

@echo off 
setlocal 
set repl=^ 
$txt=false;^ 
if ($2=='') stdout.WriteLine($1);^ 
else if ($2=='true') stderr.WriteLine($1);^ 
else $txt=$0; 

call jrepl "^(.+):=(.*)$" "%repl%" /jmatchq^ 
    /f Config.mak /o unprocessed.txt >empty.txt 2>true.txt 

Если все, что вам нужно сделать, это классифицировать строки в три разные файлы, не заботясь о отгонке :=true и := части для пустых и истинных линий, то есть это очень простое чистое пакетное решение, использующее ничего, кроме FINDSTR.

@echo off 
set "file=Config.mak" 
findstr /r ".:=$" "%file%" >empty.txt 
findstr /r ".:=true$" "%file%" >true.txt 
findstr /r ".:=" "%file%" | findstr /r /v ":=$ :=true$" >unprocessed.txt