简体   繁体   中英

Windows Batch, Split File by Delimiter, refinement

I have a folder full of text files that I need to split based on the (optional) presence of a delimiter. I found an answer for how to actually split the file here: Split text file into 2 files by separator

@echo off&setlocal
set "file=_frmCore.frm"
for /f "delims=[]" %%i in ('^<"%file%" find /n "SearchTermHere"') do set "split=%%i"
(for /f "tokens=1*delims=[]" %%i in ('^<"%file%" find /n /v ""') do if %%i lss %split% echo(%%j)>"%file%.new1"
<"%file%">"%file%.new2" more +%split%
type "%file%.new?"

Works great for what it is, but I need a few refinements and not sure where to start. Looking for:

  1. Wrap it in a loop for all files in the directory (no subfolders to worry about)
  2. "SearchTermHere" is the first on a line (the only on a line), with a specific term on the previous line that I'd rather match for safety... how can I tell it "PreviousLine/r/nSearchTermHere/r/n"? Unsure of the correct syntax here.
  3. Rather than creating two new files, move the "after search term" portion to a new file and remove it from the original
  4. Parameterize folder name to operate in so I can call from other programs

(apologies... I've tried deciphering this code and finding out what does what and trying to go from there, but this stuff is not my cup of tea and a strong push in the right direction would be wonderful)

@ECHO OFF >NUL
SETLOCAL enableextensions
rem enabledelayedexpansion
set "_files=*.frm"
set "_sfind=SearchTermHere"
if not "%~1"=="" if exist "%~1\" (
  pushd "%~1"
  set "_popd=popd"
) else ( set "_popd=" )
for /F "delims=" %%G in ('findstr /m "^%_sfind%$" %_files%') do (
  type NUL > "%%G.new1"
  type NUL > "%%G.new2"
  for /f "delims=:" %%i in ('findstr /n "^%_sfind%$" "%%G"') do (
    for /f "tokens=1* delims=:" %%I in ('findstr /n "^" "%%G"') do (
        if %%I lss %%i (
          >> "%%G.new1" echo(%%J
        )
        if %%I gtr %%i (
          >> "%%G.new2" echo(%%J
        )
    )
  )
  rem remove `ECHO` from next line no sooner than debugged!
  ECHO move /Y "%%G.new1" "%%G" 
  type "%%G.new?"
)
%_popd%

Changes made in your code:

  1. Wrap it in a loop for all files in the directory : see for /F "delims=" %%G loop against all files matching your criteria: findstr /m "^%_sfind%$" %_files% .
  2. "SearchTermHere" is the first on a line (the only on a line) : ^ = beginning of line and $ = end of line in findstr /m "^%_sfind%$" %_files% ; used findstr command rather than find .
  3. Rather than creating two new files, move the "after search term" portion to a new file and remove it from the original : see the move /Y "%%G.new1" "%%G" workaround. Operational move command is ECHO ed here merely for debugging purposes. Remove ECHO from that line no sooner than debugged !
  4. Parameterize folder name to operate in so I can call from other programs :
    • call "batch path\\31749577.bat" "folder path"
    • see %~1 test: if a parameter is supplied to the batch and represents a folder, (more in Command Line arguments (Parameters) ) and
    • see pushd - popd pair : PUSHD changes the current directory/folder and store the previous folder/path for use by the POPD command.

The tricky <"%%G">"%%G.new2" more +%%i command substituted with less effective but clear to understand if %%I gtr %%i ( ... inside the %%I loop. However, next code snippet (entire %%G loop) will work as well:

for /F "delims=" %%G in ('findstr /m "^%_sfind%$" %_files%') do (
  for /f "delims=:" %%i in ('findstr /n "^%_sfind%$" "%%G"') do (
    >"%%G.new1" (for /f "tokens=1* delims=:" %%I in ('
         findstr /n "^" "%%G"') do if %%I lss %%i echo(%%J)
    <"%%G">"%%G.new2" more +%%i
  )
  rem remove `ECHO` from next line no sooner than debugged!
  ECHO move /Y "%%G.new1" "%%G" 
  type "%%G.new?"
)

Excuse me. Although your description is extensive, it is also confusing. The Batch file below:

  • Search for a line that is "SearchTermHere".
  • If the previous line is "PreviousLine": Move from line after SearchTerm up to end of file to another file
  • Repeat previous process on all files in folder.

.

@echo off
setlocal EnableDelayedExpansion

set "find=SearchTermHere"
set "prevLine=PreviousLine"

rem Process the folder given in parameter
cd %1

rem Process all files in folder
for /F "delims=" %%F in ('dir /A-D /B') do (

   rem Get the line number of the search line - 1
   set "numLines="
   for /F "delims=:" %%a in ('findstr /N "^%find%$" "%%F"') do set /A "numLines=%%a-1"
   if defined numLines (

      rem Open a code block to read-input-file/create-output-file
      < "%%F" (

         rem Copy numLines-1 lines
         for /L %%i in (1,1,%numLines%) do (
            set "line="
            set /P "line="
            echo(!line!
         )

         rem If the line before search is prevLine
         if "!line!" equ "%prevLine%" (
            rem Copy just the search line to original file
            set /P "line="
            echo !line!
            rem and copy the rest of lines to another file
            findstr "^" > "%%~nF-PART2%%~xF"
         )

      ) > "%%F.tmp"

      if exist "%%~nF-PART2%%~xF" (
         rem Replace original file with created output file (first part)
         move /Y "%%F.tmp" "%%F" > NUL
      ) else (
         rem Remove the output file
         del "%%F.tmp"
      )

   )

)

For a further explanation of this method, see this post .

Sorry, I was unable to use either of the proposed solutions. However they did help - I spent the last two days learning about the (odd) syntaxes and operations involved in batch files and came up with the following. It doesn't do quite everything that I was looking for (and I altered the program that outputs the files a bit for further support), but it does get the job done:

@ECHO off
setlocal EnableDelayedExpansion

:: change the working directory to match the input
cd /D %~d1
cd %~p1\

:: loop all .frm files and find the CodeBehindForm string
for %%F in (*.frm) do (

 for /F "delims=[]" %%a in ('^<%%F find /n "CodeBehindForm"') do (
    if %%a gtr 0 ( 
        for /F "tokens=1*delims=[]" %%i in ('^<"%%F" find /n /v ""') do if %%i gtr %%a echo(%%j)>>"%%~nF.vb" 
        for /F "tokens=1*delims=[]" %%i in ('^<"%%F" find /n /v ""') do if %%i lss %%a echo(%%j)>>"%%~nF.fwm" 

        :: if the codebehind was found and parsed out, there's a .fwm and .vb file
        :: remove the original
        if exist %%~nF.vb del %%F
    )
)
:: change the .fwm extensions back to their original .frm extensions
ren *.fwm *.frm

I'm sure it's not "correct" in many ways, but for now it gets the job done.

Thanks for the help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM