Find the line with the special character in the text file and add a line break before each entry

I have a text file that contains one long line:

ISA*00*GARBAGE~ST*TEST*TEST~CLP*TEST~ST*TEST*TEST~CLP*TEST~ST*TEST*TEST~CLP*TEST~GE*GARBAGE*~ 

And I need it to look like this:

 ~ST*TEST*TEST~CLP*TEST ~ST*TEST*TEST~CLP*TEST ~ST*TEST*TEST~CLP*TEST 

At first I tried to add a line on each ~ST to break the line up, but I can’t do this for life. I tried various scripts, but I thought that find / replace script would work best.

 @echo off setlocal enabledelayedexpansion set INTEXTFILE=test.txt set OUTTEXTFILE=test_out.txt set SEARCHTEXT=~ST set REPLACETEXT=~ST for /f "tokens=1,* delims=~" %%A in ( '"type %INTEXTFILE%"') do ( SET string=%%A SET modified=!string:%SEARCHTEXT%=%REPLACETEXT%! echo !modified! >> %OUTTEXTFILE% ) del %INTEXTFILE% rename %OUTTEXTFILE% %INTEXTFILE% 

Found here How to replace substrings in a windows batch file

But I'm stuck because (1) the special character ~ makes the code not work at all. This gives me this result:

 string:~ST=~ST 

The code does nothing if you use quotation marks around "~ST" . And (2) I can't figure out how to add line breaks to ~ST .

The final task for this is to delete the lines ISA*00*blahblahblah and ~GE*blahblahblah after all splits have been completed. But I'm stuck on splitting in the ~ST part.

Any suggestions?

+6
source share
4 answers
 @echo off setlocal EnableDelayedExpansion rem Set next variable to the number of "~" chars that delimit the wanted fields, or more set "maxTokens=7" rem Define the delimiters that starts a new field set "delims=/ST/GE/" for /F "delims=" %%a in (test.txt) do ( set "line=%%a" set "field=" rem Process up to maxTokens per line; rem this is a trick to avoid a call to a subroutine that have a goto loop for /L %%i in (0,1,%maxTokens%) do if defined line ( for /F "tokens=1* delims=~" %%b in ("!line!") do ( rem Get the first token in the line separated by "~" delimiter set "token=%%b" rem ... and update the rest of the line set "line=%%c" rem Get the first two chars after "~" token like "ST", "CL" or "GE"; rem if they are "ST" or "GE": for %%d in ("!token:~0,2!") do if "!delims:/%%~d/=!" neq "%delims%" ( rem Start a new field: show previous one, if any if defined field echo !field! if "%%~d" equ "ST" ( set "field=~%%b" ) else ( rem It is "GE": cancel rest of line set "line=" ) ) else ( rem It is "CL" token: join it to current field, if any if defined field set "field=!field!~%%b" ) ) ) ) 

Input:

 ISA*00*GARBAGE~ST*TEST1*TEST1~CLP*TEST1~ST*TEST2*TEST2~CLP*TEST2~ST*TEST3*TEST3~CLP*TEST3~GE*GARBAGE*~CLP~TESTX 

Output:

 ~ST*TEST1*TEST1~CLP*TEST1 ~ST*TEST2*TEST2~CLP*TEST2 ~ST*TEST3*TEST3~CLP*TEST3 
+3
source

How can you find and replace text in a file using the Windows command line environment?

This section contains many methods on how to perform a replacement from the command line.

My favorite is the free Xchang32 tool from the Clay Utilities for Win32 collection , because it can even be used for binary files.

The following command is used for this task:

 Xchang32.exe "Test.txt" "~ST" "^x0D^x0A~ST" 

^x0D is the hexadecimal notation for carriage return.
^x0A is the hexadecimal notation for the string.

Why use the Xchang32.exe tool to search and replace files instead of the standard Windows commands?

This is similar to the question why using a hammer to bring a nail into the board, and not, for example, diagonal pliers. You can drive a nail into a board with diagonal pliers, as I already did in the past. But it is much easier to use a hammer, which is designed to bring nails to the board.

Therefore, using standard Windows commands to replace a line in a file is possible, although it is not intended for. But it’s much easier to use a free tool, for example Xchang32.exe , which is designed specifically for this task.

The following batch file can be used for the entire task with GARBAGE being an unknown string.

 @echo off Xchang32.exe "Test.txt" "~ST" "^x0D^x0A~ST" >nul if errorlevel 1 goto :EOF setlocal EnableDelayedExpansion Xchang32.exe "Test.txt" "~GE" "^x0D^x0A~GE" >nul del "%TEMP%\Test.tmp" 2>nul for /F "usebackq skip=1 delims=" %%L in ("Test.txt") do ( set "Line=%%L" if "!Line:~1,2!" == "ST" echo %%L>>"%TEMP%\test.tmp" ) move /Y "%TEMP%\Test.tmp" "Test.txt" endlocal 
+1
source

~ cannot be used as the first character of a search string in the substring syntax %VARIABLE:SEARCH_STRING=REPLACE_STRING% , because it is used to indicate the extension of the substring %VARIABLE:~POSITION,LENGTH% (enter set/? for more information).

Suppose your text file contains only one line of text and does not exceed a size of about 8 KB. I see the following version of your task. This script uses the substitution syntax %VARIABLE:*SEARCH_STRING=REPLACE_STRING% ; * determines that everything was before the first appearance of SEARCH_STRING :

 @echo off setlocal EnableExtensions EnableDelayedExpansion rem initialise constants: set "INFILE=test_in.txt" set "OUTFILE=test_out.txt" set "SEARCH=ST" set "TAIL=GE" rem read single-line file content into variable: < "%INFILE%" set /P "DATA=" rem remove everything before first `~%SEARCH%`: set "DATA=~%SEARCH%!DATA:*~%SEARCH%=!" rem call sub-routine, redirect its output: > "%OUTFILE%" call :LOOP endlocal goto :EOF :LOOP rem extract portion right to first `~%SEARCH%`: set "RIGHT=!DATA:*~%SEARCH%=!" rem skip rest if no match found: if "!RIGHT!"=="!DATA!" goto :TAIL rem extract portion left to first `~%SEARCH%`, including `~`: set "LEFT=!DATA:%SEARCH%%RIGHT%=!" rem the last character must be a `~`; rem so remove it; `echo` outputs a trailing line-break; rem the `if` avoids an empty line at the beginning; rem the unwanted part at the beginning is removed implicitly: if not "!LEFT:~,-1!"=="" echo(!LEFT:~,-1! rem output `~%SEARCH%` without trailing line-break: < nul set /P "DUMMY=~%SEARCH%" rem store remainder for next iteration: set "DATA=!RIGHT!" rem loop back if remainder is not empty: if not "!DATA!"=="" goto :LOOP :TAIL rem this section removes the part starting at `~%TAIL%`: set "RIGHT=!DATA:*~%TAIL%=!" if "!RIGHT!"=="!DATA!" goto :EOF set "LEFT=!DATA:%TAIL%%RIGHT%=!" rem output part before `~%TAIL%` without trailing line-break: < nul set /P "DUMMY=!LEFT:~,-1!" goto :EOF 

The following restrictions apply to this approach:

  • input file contains one line;
  • input file size does not exceed about 8 kb;
  • there is only one ~GE instance that occurs after all ~ST instances;
  • at least one character always exists between two adjacent instances of ~ST ;
  • there are no special characters in the file, such as: SPACE , TAB , " , % , ! , = ;
0
source

Do not reinvent the wheel, use the regexp replacement tool, such as sed or JREPL.BAT :

 call jrepl "^.*?~ST(.+?)~GE.*$" "'~ST'+$1.replace(/~ST/g,'\r\n$&')" /jmatch <in.txt >out.txt 
0
source

All Articles