I have a text file that is generated daily that has between 20 and 50 lines, each ending with a set delimiter, currently ~ but that can be changed to anything. I want to take this text file and split it into 20 to 50 different files, with one line per file. Ideally I'd like to do this from a windows batch file, or at least a program that I can script to run daily. Appreciate any help you can provide, thanks!
Sample Input File:
GS*SH*CSMZ9*20131209*0908*000000001*X*004010|ST*856*0001|BSN*00*000000001~
GS*SH*CSMZ9*20131209*0912*003400004*X*004010|SG*834*0001|TSN*00*000000004~
GS*SH*CSMZ5*20131209*1001*000040007*X*004010|ST*855*0001|BSN*00*000000007~
GS*SH*CSMZ9*20131209*1019*000000010*X*004010|SG*856*0001|BGN*00*000000010~
for /f "tokens=1*delims=:" %%a in ('findstr /n "^" "file.txt"') do for /f "delims=~" %%c in ("%%~b") do >"text%%a.txt" echo(%%c
I propose python here. Much more readable that any shell script.
f=open("filename")
lines = f.read().split('~')
for (n, line) in enumerate(lines):
open( "newname{}".format(n), "w" ).write(line)
This should create files called 00000001.txt and increment the number for each line.
If any line contains ! then it needs an extra modification.
#echo off
setlocal enabledelayedexpansion
set c=0
for /f "delims=" %%a in (file.txt) do (
set /a c+=1
set name=0000000!c!
set name=!name:~-8!.txt
>!name! echo %%a
)
#ECHO OFF
SETLOCAL
SET "destdir=c:\destdir"
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n "." q21239387.txt') DO (
>"%destdir%\filename%%a.txt" ECHO(%%b
)
GOTO :EOF
where q21239387.txt is the name of the file I used as input for testing.
Files filename1.txt..filename99.txt created in the destination directory (99 is # lines in the file)
Note - will not correctly output source lines that begin with : if that is a problem.
Related
In below code i am tring to fetch the line no of string "AXX0000XXXA" from file data.txt,then fetching line by line and printing target.txt file,in between if the line reach the find line no i am adding one more line from file temp.txt.The code is working fine with the less nos of records(tested with 150 lines-File Size 100 kb),but when i am processing with 50K records(File Size 25MB) it is taking more then 25 minutes to process.could you please help me how i will process same in less time.
#echo off
setlocal enabledelayedexpansion
for /f "delims=:" %%a in ('findstr /n "AXX0000XXXA" "C:\Users\23456\Desktop\data.txt"') do (set find_line=%%a)
set /a counter=0
for /f "usebackq delims=" %%b in (`"findstr /n ^^ C:\Users\23456\Desktop\data.txt"`) do (
set curr_line=%%b
set /a counter=!counter!+1
if !counter! equ !find_line! (
type temp.txt >> target.txt
)
call :print_line curr_line
)
endlocal
:print_line
setlocal enabledelayedexpansion
set line=!%1!
set line=!line:*:=!
echo !line!>>target.txt
endlocal
Your code uses three Batch file constructs that are inherently slow: call command, >> append redirection and setlocal/endlocal, and these constructs are executed once per each file line! It would be faster to include the subroutine into the original code to avoid the call and setlocal commands, and an echo !line!>>target.txt command imply open the file, search for the end, append the data and close the file, so it is faster to use this construct: (for ...) > target.txt that just open the file once. An example of a code with such changes is in Compo's answer.
This is another method to solve this problem that may run faster when the search line is placed towards the beginning of the file:
#echo off
setlocal enabledelayedexpansion
for /f "delims=:" %%a in ('findstr /n "AXX0000XXXA" "C:\Users\23456\Desktop\data.txt"') do (set /A find_line=%%a-1)
call :processFile < "C:\Users\23456\Desktop\data.txt" > target.txt
goto :EOF
:processFile
rem Duplicate the first %find_line%-1 lines
for /L %%i in (1,1,%find_line%) do (
set /P "line="
echo !line!
)
rem Insert the additional line
type temp.txt
rem Copy the rest of lines
findstr ^^
exit /B
This should create target.txt with content matching data.txt except for an inserted line taken from tmp.txt immediately above the line matching the search string, AXX0000XXXA.
#Echo Off
Set "fSrc=C:\Users\23456\Desktop\data.txt"
Set "iSrc=temp.txt"
Set "sStr=AXX0000XXXA"
Set "fDst=target.txt"
Set "iStr="
Set/P "iStr="<"%iSrc%" 2>Nul
If Not Defined iStr Exit/B
Set "nStr="
For /F "Delims=:" %%A In ('FindStr/N "%sStr%" "%fSrc%" 2^>Nul') Do Set "nStr=%%A"
If Not Defined nStr Exit/B
( For /F "Tokens=1*Delims=:" %%A In ('FindStr/N "^" "%fSrc%"') Do (
If "%%A"=="%nStr%" Echo %iStr%
Echo %%B))>"%fDst%"
I have made it easy for you to change your variable data, you only need to alter lines 3-6.
I have assumed that this was your intention, your question was not clear, please accept my apologies if I have assumed incorrectly.
I have a file "file.txt" which contains the output of "dir /s /b *.c"
I want to write this whole content of file.txt in a single variable .
Any ideas?
The usual way to treat questions like this one is to reply: "What do you want this for?". However, your question is pure and simple, so here is the answer. The Batch file below not just store the contents of file.txt in a single variable, but it also later process the variable value as individual lines.
EDIT: I added the method to extract individual lines from the variable value as substrings.
#echo off
setlocal EnableDelayedExpansion
rem Create variables with LF and CR values:
set LF=^
%empty line 1/2, don't remove%
%empty line 2/2, don't remove%
for /F %%a in ('copy /Z "%~F0" NUL') do set CR=%%a
rem Store the contents of file.txt in a single variable,
rem end each line with <CR><LF> bytes
set "variable="
for /F "delims=" %%a in (file.txt) do (
set "variable=!variable!%%a!CR!!LF!"
)
rem 1- Show the contents of the variable:
echo !variable!
rem 2- Process the contents of the variable line by line
echo/
set i=0
for /F "delims=" %%a in ("!variable!") do (
set /A i+=1
echo Line !i!- %%a
)
rem Get the starting position and length of each line inside the variable
set /A i=0, lastStart=0
for /F "delims=:" %%a in (
'(cmd /V:ON /C set /P "=^!variable^!" ^& echo/^) ^<NUL ^| findstr /O "^^"'
) do (
set /A len[!i!]=%%a-lastStart-2, i+=1
set /A start[!i!]=%%a, lastStart=%%a
)
set "len[0]="
set "start[%i%]="
set /A lastLine=i-1
rem 3- Extract individual lines from the variable contents as substrings
:getNumber
echo/
set "num="
set /P "num=Enter line number (nothing to end): "
if not defined num goto end
if %num% gtr %lastLine% echo Invalid number & goto getNumber
for /F "tokens=1,2" %%i in ("!start[%num%]! !len[%num%]!") do (
echo Line %num%- !variable:~%%i,%%j!
)
goto getNumber
:end
You must note that Batch variables can only store a maximum of 8K characters.
No. But you can go through the lines one by one.
for /f "delims=" %A in (file.txt) do echo %A
Maybe say what you are trying to achieve. Knowledge of C won't help you in batch because it's contary for historical reasons.
You can use set /p:
set /p foo=<file.txt
See also this question.
Batch-Script is a very limited tool with a primitive support for multi-line variables (with specific hacks that will not work as expected for this sceneario but if you are interested see this).
The only reasonable solution is to move to a capable language, which is every else less Batch-Script.
I've been tasked with extracting some data from a text file and I was wondering if anyone knows a quick cmd method to my problem.
The file I need to search is quite large, consisting of repetitive records.
What I'm looking to do is search for one line of text, say:
'searchForThisLineOfText'
Then, when it's found, go to the next line down from that text, and write that line to a file.
So the contents of the file looks somting like this:
searchForThisLineOfText
563473
someOtherLine
34583933
anotherline
2342
searchForThisLineOfText
3424
someOtherLine
34583933
anotherline
2342
From that, I would like to write the numbers 563473 and 3424 to a file.
Anybody have any ideas on how to do this?
Thanks in advance.
#ECHO OFF
SETLOCAL
SET "found="
(
FOR /f "delims=" %%a IN (q25871330.txt) DO (
IF DEFINED found ECHO %%a
IF "%%a"=="searchForThisLineOfText" (SET "found=Y") ELSE (SET "found=")
)
)>newfile.txt
GOTO :EOF
I used a file named q25871330.txt containing your data for my testing.
Produces newfile.txt
This assumes that the blank lines are not actually in the text file.
#echo off
type "file.txt" | findrepl "searchForThisLineOfText" /o:1:1 >"newfile.txt"
pause
This uses a helper batch file called findrepl.bat (by aacini) - download from: https://www.dropbox.com/s/rfdldmcb6vwi9xc/findrepl.bat
Place findrepl.bat in the same folder as the batch file or on the path.
This will generate a temporary file with the number of the lines that need to be retrieved and then retrieves the required lines
#echo off
setlocal enableextensions enabledelayedexpansion
rem We will need a temporary file
set "tempFile=%temp%\%~nx0.%random%.tmp"
rem Get the number of the lines that we need to retrieve
(
for /f "delims=:" %%a in ('
findstr /n /l /c:"searchText" "data.txt"
') do ( set /a "n=%%a+1" & echo(!n!:)
)>"%tempFile%"
rem Retrieve the indicated lines to the output file
(
for /f "tokens=1,* delims=:" %%a in ('
findstr /n /r /c:"^" "data.txt"
^| findstr /b /l /g:"%tempFile%"
') do echo(%%b
)>"outputFile.txt"
rem Remove the temporary file
del "%tempFile%" > nul 2>nul
Basically I'm trying to write a batch file to insert some code into multiple files. Here are the details of what I'm tring to accomplish:
1. The input string comes from a file test.txt.
2. The string needs to be inserted as the second line of destination files.
3. Destination files are all the .xml files under the same direction as the batch file.
I suppose I should use a FOR loop to go through all .xml files. Something like
for /f %%i in ('dir /b *.xml') do ()
I've read though some tutorials and posts but can't find a way to add anything to files in a loop. Using Echo or TYPE doesn't seems to work for each file in a loop. How do I modify files in a loop?
Also to insert to a certain number of line some post say the file needs to be put into a variable. But my files are pretty large, which I don't want to put into variables. Is there another way to insert into a certain line in a file?
#ECHO OFF
SETLOCAL
FOR /f "delims=" %%i IN ('dir /b *.xml') DO (
SET line2=Y
(
FOR /f "usebackqdelims=" %%x IN ("%%i") DO (
ECHO(%%x
IF DEFINED line2 TYPE Line2.txt
SET "line2="
)
)>"%%~ni.lmx"
)
GOTO :EOF
This should work for you - but it will delete empty lines.
#echo off
set /P string=< test.txt
for %%a in (*.xml) do (
(for /F "usebackq tokens=1* delims=:" %%b in ('findstr /N "^" "%%a"') do (
if %%b equ 2 echo %string%
set "line=%%c"
setlocal EnableDelayedExpansion
echo(!line!
endlocal
)) > "%%a.new"
)
New files have .xml.new extension; you may add a couple lines to delete original .xml files and rename .xml.new ones to .xml.
if my file conatins below text :
sampleA1xxx sampleA2yyyy sampleA3zzzzz ... sampleA4hhhhh
I want to find sampleA4 and display sampleA4hhhh using windows batch script.
Thats is my output should be: sampleA4hhhhh
Could anyone please help me.
take a batch or have a look at GNUWin sed:
>type file
^^sampleA1xxx ^^sampleA2yyyy ^^sampleA3zzzzz ^^sampleA4hhhhh
>sed -r "s/.*(\b\w+4\w+)/\1/" file
sampleA4hhhhh
#echo off
setlocal EnableDelayedExpansion
set target=sampleA4
set len=8
for /F "delims=" %%a in ('findstr "%target%" theFile.txt') do (
for %%b in (%%a) do (
set word=%%b
if "!word:~0,%len%!" equ "%target%" (
echo !word:~%len%!
)
)
)
#ECHO OFF
SETLOCAL
FOR /f "delims=" %%i IN (q17316008.txt) DO SET line=%%i
SET line=%line:^= %
SET line=%line:*sampleA4=sampleA4%
FOR %%i IN (%line:^^= %) DO SET line=%%i&GOTO :done
:done
ECHO %line%
GOTO :EOF
This should do what I gather to be the task. It assumes that the "samplea4" string exists in the file's single line, is case-insensitive and the line doesn't exceed the ~8K limit on line length.
Simply replace the carets with spaces, lop off the leading characters to the first occurrence of the target string, and process that target string as a list; the first element will be the required string, so stop the processing when it's available.
OK, I tried this myself with a similar case and it worked fine:
for /f "tokens=4 delims=^^" %%a in (seperate.txt) do (echo %%a)
pause
Note: This is designed for a batch file, and replace the 4 after "tokens=" with whichever separated text you want to stop at.
Hope this helped,
Yours Mona.