I have a task to cut off the block starting from certain string in the middle of a file and then to save this upper part of the file into a new file.
;---- Some text A
aaaaaaa1111
……..
aaaaaaa2222
;-----Some text B
bbbbbbbbb1111
…………..
bbbbbbbbb2222
Now I am looking for a batch file to cut off the part starting from:
;-----Some text B
So after cut, the new file looks like:
;---- Some text A
aaaaaaa1111
……..
aaaaaaa2222
All the part starting from:
;-----Some text B
bbbbbbbbb1111
…………..
bbbbbbbbb2222
has been cut off.
I tried to use the Function from DOStip then call that function as below:
#ECHO OFF
REM.-- Prepare the Command Processor
SETLOCAL ENABLEEXTENSIONS
SETLOCAL ENABLEDELAYEDEXPANSION
echo.Extracting hello world block into "Load_SDK.M83" file
call:extractFromFile ";---- Some text A" ";---- Some text B">"Load_SDK.M83"
:extractFromFile - extract lines from a file between begin and end mark
:: - %~1: begin mark, use '...$' mark to allow variable substitution
:: - %~2: optional end mark, default is end of file
:: - %~3: optional source file, default is THIS file
SETLOCAL
set bmk=;---- Some text A
set emk=;---- Some text B
set src=C:\Files\Load_all.M83
set /a b=-1
set /a e=-1
if "%src%"=="" set src=%~f0& ::- if no source file then assume THIS file
for /f "tokens=1,* delims=:" %%a in ('"findstr /n /b /c:"%bmk%" "%~f0""') do (
set b=%%a
set bmk=%%b
)
if /i %b%==-1 echo.ERROR: begin mark '%bmk%' not found in '%src%'&GOTO:EOF
if "%emk%"=="" (set /a e=2000000000) ELSE (
for /f "delims=:" %%a in ('"findstr /n /b /c:"%emk%" "%~f0""') do (
if /i %b% LSS %%a if /i !e!==-1 set e=%%a& rem -- find only the first one after b
)
)
if /i %e%==-1 echo.ERROR: end mark '%emk%' missing in '%src%'&GOTO:EOF
if /i %b% GEQ %e% echo.ERROR: end mark '%emk%' detected before begin mark '%bmk%' in '%src%'&GOTO:EOF
for /f "delims=: tokens=1,*" %%a in ('"findstr /v /n /b /c:"#$*ReturnAll*$#" "%src%""') do (
if /i %b% LSS %%a if /i %%a LSS %e% (
if "%bmk:~-1%"=="$" (
rem --sustitution variables within %%b
call echo.%%b
) ELSE (
rem --no variable substitution
echo.%%b
)
)
)
GOTO:EOF
Based on my comment, a one line single For loop with an If and a GoTo seems to perform the task as shown in your question:
#(For /F UseBackQDelims^=^ EOL^= %%A In ("source.txt") Do #If /I Not "%%A"==";-----Some text B" (Set /P "=%%A"<Nul&Echo=) Else GoTo :EOF)>"result.txt"
Related
I'm using below code for inserting text contents after a specific line/string is found. How can I modify this code to insert all the lines before the occurrence of line/string in file ?
#echo off
for /f "delims=:" %%i in ('findstr /rinc:"string" test.txt') do (set line_no=%%i)
for /f "skip=%line_no% delims=" %%a in ('type test.txt') do (echo %%a >> output.txt)
i.e if test.txt contains:
abc
def
p q r
u v w
xyz
If the the search is for line p q r, the output should be:
abc
def
Test if the line matches the sting, if it does, exit loop:
#echo off
(for /f "delims=" %%i in ('type test.txt') do (
if "%%i" == "p q r" exit /b
echo %%i
)
)>output.txt
To include everything up to and including the search string, simply swop the if statement and the echo lines.
#echo off
(for /f "delims=" %%i in ('type test.txt') do (
echo %%i
if "%%i" == "p q r" exit /b
)
)>output.txt
as a replacement to your original code:
#echo off
set str=
(for /f "delims=" %%i in ('type test.txt') do (
if defined str echo %%i
if "%%i" == "p q r" set str=1
)
)>output.txt
and to include the search string.
#echo off
set str=
(for /f "delims=" %%i in ('type test.txt') do (
if "%%i" == "p q r" set "str=1"
if defined str echo %%i
)
)>output.txt
Note that this will also remove any empty lines from the original file.
#ECHO OFF
SETLOCAL
rem The following settings for the source directory, destination directory, filenames,
rem and output filename are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
SET "filename1=%sourcedir%\q71800622.txt"
SET "filename2=%sourcedir%\q71800622_2.txt"
SET "outfile=%destdir%\outfile.txt"
SET "targetline=p q r"
:: Set these flags to Y for Yes or *nothing* for No (eg. SET "showbeforetarget=")
:: show??target will show that part of the first file
:: include...??insert will show the target line before/after the insert (or both)
SET "showbeforetarget=Y"
SET "showaftertarget=Y"
SET "includetargetbeforeinsert=Y"
SET "includetargetafterinsert=Y"
SET "targetfound="
(
FOR /f "usebackqdelims=" %%b IN ("%filename1%") DO (
ECHO %%b|FINDSTR /x /L /C:"%targetline%" >NUL
IF ERRORLEVEL 1 (
IF DEFINED showbeforetarget ECHO %%b
IF DEFINED showaftertarget IF DEFINED targetfound ECHO %%b
) ELSE (
SET "targetfound=Y"
SET "showbeforetarget="
IF DEFINED includetargetbeforeinsert ECHO %%b
TYPE "%filename2%"
IF DEFINED includetargetafterinsert ECHO %%b
)
)
)>"%outfile%"
GOTO :EOF
This routine will allow a file to be inserted at the point where findstr finds a match (I've set it to /x exactly match the /L literal constant string shown as provided by OP).
It can be set to show/not show the portion before the target string, to show/not show the portion after the target string, and to show/not show the target string before or after the inserted lines (or both) from the second file.
I have a text file that I would like to edit and therefore would like to remove the last line. I have the following code for this:
for /f "delims=" %%a in (input.txt) do (
echo/|set /p ="%%a%"
)>>output.txt
input:
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
output:
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
Now I would like to edit the data in groups for example by the first value, so that I have the following output:
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
If I replace the FOR /F "delims=" %%a in (input.txt) do … loop with an equivalent FOR %%a in … loop:
#ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
set "_gruppeName="
(
for %%a in (
"GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
) do (
for /f "tokens=1 delims=;" %%A in ("%%~a") do (
if /I NOT "%%~A"=="!_gruppeName!" (
if defined _gruppeName echo(
set "_gruppeName=%%~A"
)
)
echo/|set /p ="%%~a"
)
echo(
)>>output.txt
REM debugging output follows
type output.txt
Output:
1st run: 2>NUL del output.txt & D:\bat\CR\61816520.bat
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
Next run: D:\bat\CR\61816520.bat
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
Your question is not clear
based on ... the first value (GRUPPEA)
is it SORTed? or just write duplicates on the same line?
#echo off
SETLOCAL EnableExtensions EnableDelayedExpansion
::VARIABLES
set "in=input.txt" IN file
set "out=output.txt" OUT file
set/a"#lines=0"
set "gruppe="
set "prevContent="
::Count lines
FOR /F %%L in ('
"findstr /N "^^" "%in%" %= do not skip empty lines =%"
') do set/a"#lines+=1" %= Get the # of lines =%
::Read IN via SET /P #LINES number of times
::Bangs (!) will be lost
<"%in%" >"%out%" (FOR /L %%# in (1 1 %#lines%) do (
set "data=" ::clear DATA
set/p"data=" ::read from IN
FOR /F tokens^=1^ delims^=^;^ eol^= %%T in ("!data!") do set "gruppe=%%T"
if NOT "!prevContent!" == "!gruppe!" (
set "prevContent=!gruppe!"
echo(
)
<nul set/p"=!data!" ::does not work with leading space, tabs, or equal signs
)) %= read file by lines via SET /P =%
exit /b
The script counts the number of lines using FINDSTR /N and a FOR /F loop to count the # of lines, which is required to execute SET /P that many times.
Tips:
Use ECHO( instead of the problematic ECHO.
Using a pipe | is very slow, as described by #jeb here. Use <nul instead
Good Afternoon!
Long time reader, first time poster! I have been having a lovely time trying to modify a working batch file to account for variability. The situation is that I have a variable-size text document that normally would be able to be split into sections of 252 lines. The code below worked like a champ:
#echo off & setlocal EnableDelayedExpansion
set param=%*
if not defined param (
echo.
echo. Usage: batchsplit [device:][pathname]filename
goto :EOF
)
set param=%param:"=%
if not exist "%param%" (
echo.
echo. File "%param%" not found
goto :EOF
)
for %%j in ("%param%") do (
set name=%%~dpnj
set ext=%%~xj
)
for /F %%j in ('type "%param%" ^| find /V /C ""') do set Full=%%j
set /A Split=%Full%/252
for /L %%G in (1,1,%Split%) do type nul > "%name%_%%G%.new"
set X=1
set N=1
set Q=1
set limit = 252
for /F "tokens=1* delims=]" %%j in ('type "%param%" ^| find /V /N ""') do (
set /A N+=1
set /A Q+=1
echo.%%k>> "%name%_!X!%.new"
if !Q! gtr 252 (
set /A X+=1
set /A Q=1
) else if !N! gtr Full (goto theend
)
)
:theend
echo split into %split% files with 252 lines each
rem pause
However, there were some changes to the formatting of the text, and now instead of four pages of 63 lines per split file, it can be completely variable. The only constant is this final line, which precedes the remaining space for a 63 line page:
ON THIS FORM IS COMPLETE AND CORRECT AS NOTED:___________________
Note that there is a single space in front of it, as well as multiple spaces, a colon, and underscore characters. Being the meathead that I am, I thought I could insert an if-then statement into the for loop to trigger the batch to split to the next page. However, I could be further from that right now. This is the code I have been smashing my head with:
rem #echo off & setlocal EnableDelayedExpansion
setlocal EnableDelayedExpansion
set param=%*
if not defined param (
echo.
echo. Usage: textsplit [device:][pathname]filename
goto :EOF
)
set param=%param:"=%
if not exist "%param%" (
echo.
echo. File "%param%" not found
goto :EOF
)
for %%j in ("%param%") do (
set Name=%%~dpnj
set ext=%%~xj
)
for /F %%j in ('type "%param%" ^| find /V /C ""') do set Full=%%j
set stopvar= ON THIS FORM IS COMPLETE AND CORRECT AS NOTED:___________________
set Split=1
echo %stopvar%
set X=1
type nul > "%name%_!X!%.new"
set N=1
set Q=1
set S=0
set L=63
for /F "tokens=1* delims=]" %%j in ('type "%param%" ^| find /V /N ""') do (
set /A N+=1
echo %N%
set /A Q+=1
echo %Q%
echo.%%k>> "%name%_!X!%.new"
if ["%%k%" == "!stopvar!"] (
set /A S+=1
)
if !Q! gtr !L! (
if !S! == 1 (
set /A X+=1
set /A Q=1
type nul > "%name%_!X!%.new"
set /A Split+=1
set S=0
)
else set /A L+=63
else if !N! gtr Full goto theend
)
:theend
echo Split into %split% files!
pause
The premise is that every 63 lines, the stop variable (S) is checked. If it is off (0) then the batch will continue to write for another 63 lines (one page). If the stopvar matches the line that is being read by the for loop, S becomes 1. When the program checks again, it will create a new file and begin writing to that new file. Right now, based on turning off #echo off the hangup is at the for loop. See below:
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>rrtextsplit texttest.txt
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>rem #echo off & setlocal Enabl
eDelayedExpansion
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>setlocal EnableDelayedExpansio
n
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set param=texttest.txt
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>if not defined param (
echo.
echo. Usage: rrtextsplit [device:][pathname]filename
goto :EOF
)
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set param=texttest.txt
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>if not exist "texttest.txt" (
echo.
echo. File "texttest.txt" not found
goto :EOF
)
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>for %j in ("texttest.txt") do
(
set Name=%~dpnj
set ext=%~xj
)
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>(
set Name=C:\Users\theangryasiancp\Desktop\TEXT_Split_Test\texttest
set ext=.txt
)
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>for /F %j in ('type "texttest.
txt" | find /V /C ""') do set Full=%j
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set Full=567
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set stopvar= ON THIS FORM IS C
OMPLETE AND CORRECT AS NOTED:___________________
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set Split=1
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>echo ON THIS FORM IS COMPLETE
AND CORRECT AS NOTED:___________________
ON THIS FORM IS COMPLETE AND CORRECT AS NOTED:___________________
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set X=1
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>type nul 1>"C:\Users\theangry
asiancp\Desktop\RRRR_Split_Test\texttest_!X!.new"
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set N=1
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set Q=1
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set S=0
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set L=63
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>
What are your thoughts? Where am I going wrong with the batch? I wish I could use something different, but alas I cannot, for internal company reasons. Thanks for your help!
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "name=q23396663"
SET "ext=.txt"
SET /a pagelength=10
SET "targetstring= ON THIS FORM IS COMPLETE AND CORRECT AS NOTED:___________________"
SET /a filenum=0
SET /a linecount=pagelength + 1
FOR /f "tokens=1*delims=]" %%a IN (
'find /v /n "" "%name%%ext%"') DO (
IF !linecount! GEQ %pagelength% (
SET /a linecount=0
SET /a filenum+=1
)
>>U:\%name%_!filenum!.new ECHO(%%b
IF "%%b"=="%targetstring%" SET /a linecount=pagelength
SET /a linecount+=1
)
GOTO :EOF
For testing purposes, I set up a file q23396663.txt containing your trigger data. I've left the destination directory as U:\ which suits me, and the pagelength at 10 which makes my testing easier.
#echo off
setlocal EnableDelayedExpansion
REM ------------------THIS SECTION SPECIFIES THE FILE-------------------------
set param=%*
if not defined param (
echo.
echo. Usage: filesplit [device:][pathname]filename
goto :EOF
)
set param=%param:"=%
if not exist "%param%" (
echo.
echo. File "%param%" not found
GOTO :EOF
)
for %%j in ("%param%") do (
set name=%%~dpnj
set ext=%%~xj
)
ECHO SPLITTING %name%.%ext% .................
REM ----------------THIS SECTION SETS THE VARIABLES---------------------------
set "trigger= ON THIS FORM IS COMPLETE AND CORRECT AS NOTED:___________________"
set /a pagelength=63
set /a filenum=0
set split=1
set /a linecount=pagelength
set stopvar=0
REM ------------------THIS SECTION IS THE FOR LOOP----------------------------
FOR /f "skip=2 tokens=1* delims=]" %%a IN (
'find /v /n "" "%name%%ext%"') DO (
SET /a linecount-=1
IF !linecount! LEQ 0 (
IF !stopvar! EQU 1 (
SET /a "linecount=pagelength"
SET /a filenum+=1
SET /a split+=1
SET /a stopvar-=1
) else set /a "linecount=pagelength"
)
echo.%%b>> "%name%_!filenum!.new"
IF "%%b"=="%trigger%" (
set /a "stopvar+=1"
REM THIS TRIGGERS TO CHANGE OUTPUT
set /a linecount+=1
REM THIS WILL ADJUST THE OUTPUT EOF
)
)
REM ----------------THIS SECTION ENDS THE FOR LOOP----------------------------
ECHO Split into %split% files!
ping 1.1.1.1 -n 1 -w 2500 > nul
REM THIS PAUSES THE BATCH FOR A SEC
As I posted in the comment above, this is just a variation of the first answer that accounts for blank spaces if they are needed to keep the output files from having unnecessary whitespace on top. This is especially helpful when a print manager is just spitting out whitespace until the end of the page before starting the next part instead of going straight to the next portion.
How can i encrypt the content in a text file using batch? and how can i decrypt it?
i have tried setting each letter to a number but i do not know how to split the string into each letter and do that.
I watched a video on youtube that help turn letters into numbers but it did not do it with a file.
this is the code he provides in the video.
#echo off
setlocal enableDelayedExpansion
set /p code=Text:
set chars=0123456789abcdefghijklmnopqrstuvwxyz
for /L %%N in (10 1 36) do (
for /F %%C in ("!chars:~%%N,1!") do (
set "code=!code:%%C=%%N!"
)
)
echo !code!
pause
Please help Thank you
#ECHO OFF
SET abet=abcdefghijklmnopqrstuvwxyz!##-/\ .0123456789
SET cipher1=8p#j4 9z\6w.ae#0u2r5o!xk-cf1b3g7hmqil/sntdvy
(
FOR /f "delims=" %%a IN (q20794050.txt) DO (
SET line=%%a
CALL :encipher
)
)>q20794050.txt.1
(
FOR /f "delims=" %%a IN (q20794050.txt.1) DO (
SET line=%%a
CALL :decipher
)
)>q20794050.txt.2
GOTO :EOF
:decipher
SET morf=%abet%
SET from=%cipher1%
GOTO trans
:encipher
SET from=%abet%
SET morf=%cipher1%
:trans
SET "enil="
:transl
SET $1=%from%
SET $2=%morf%
:transc
IF /i "%line:~0,1%"=="%$1:~0,1%" SET enil=%enil%%$2:~0,1%&GOTO transnc
SET $1=%$1:~1%
SET $2=%$2:~1%
IF DEFINED $2 GOTO transc
:: No translation - keep
SET enil=%enil%%line:~0,1%
:transnc
SET line=%line:~1%
IF DEFINED line GOTO transl
ECHO %enil%
GOTO :eof
Here's a way to do it using a simple Cæsar (substitution) code.
abet can be set (possibly from a file) to the set of characters that you want to encode. Similarly, cipher1 can be set to the transled set - just make sure that each character in abet also appears in cipher1.
Any character that appears in the input text but not in abet will not be translated.
I used q20794050.txt:
The quick brown fox [jumps] {over} the lazy dog 9876543210.
9876543210 The quick brown fox !##-/\ jumps over the lazy dog.f
Which was encoded to q20794050.txt.1 :
5z4huo\#whp2#xeh #kh[6oa0r]h{#!42}h5z4h.8c-hj#9hyvdtns/liqm
yvdtns/liqh5z4huo\#whp2#xeh #khf1b3g7h6oa0rh#!42h5z4h.8c-hj#9m
(Note that there is a Space at the end of that last line...)
And was successfully disencrypted to q20794050.txt.2
Note: the above won't handle certain problem characters like %&|><
I've only used lower-case so any upper-case would be translated to lower-case by the process. If you remove the /i from the IF statement, then case will be preserved, but you'd have to add the upper-case letters to abet and cipher1 else the encrypted file will contain the upper-case characters verbatim.
Note that
(for...do (...))>somefilename
will create a new file somefilename containing any data ECHOed - even if the ECHO occurs in a subroutine.
#echo off
setlocal enableDelayedExpansion
for /f "tokens=* delims= " %%h in ('type %1') do (
set text=%%h
)
set chars=0123456789abcdefghijklmnopqrstuvwxyz
for /L %%N in (10 1 36) do (
for /F %%C in ("!chars:~%%N,1!") do (
set "text=!text:%%C=-%%N!"
)
)
echo !text! > %userprofile%\Desktop\encrypted.txt
pause
(using a different .bat file)
#echo off
setlocal enableDelayedExpansion
for /f "tokens=* delims= " %%h in ('type %1') do (
set text=%%h
)
set chars=0123456789abcdefghijklmnopqrstuvwxyz
for /L %%N in (10 1 36) do (
for /F %%C in ("!chars:~%%N,1!") do (
set "text=!text:%%N=%%C!"
)
)
for /f %%K in ("!text!") do (
set "text=!text:-=!"
)
echo !text! > %userprofile%\Desktop\decrypted.txt
pause
In Linux (Bash) there is a very useful functionality for dumping literal text out to another file like this:
cat > see.txt << EOF
contents going into
my file
EOF
What I need is the equivalent for a Windows batch script. I haven't found this kind of functionality built-in, but I was thinking I could write a subroutine to do it (I don't want to rely on anything that isn't natively in Windows since XP), but I'm having trouble. Here's what I have so far with help from various sources:
call:catMyChunk myCustomText c:\see.txt
exit /b
goto:myCustomText
This is my test file
Hope you like it.
<got these>
% and these %
! these too
yeah
:myCustomText
:catMyChunk
::Should call this function with 2 args, MYDELIM and outFile.txt
::where is to be catted to outFile.txt
::and text starts with <beginning of line>goto:MYDELIM
::and ends with <beginning of line>:MYDELIM
set searchStart=goto:%~1
set searchStop=:%~1
set outFile=%~2
set startLine=0
set endLine=0
for /f "delims=:" %%a in ('findstr -b -n !searchStart! %~dpnx0') do set "startLine=%%a"
for /f "delims=:" %%a in ('findstr -b -n !searchStop! %~dpnx0') do set "endLine=%%a"
set /a linesLeftToRead=%endLine% - %startLine%
del %outFile%
if "%linesLeftToRead%" LEQ "0" (
echo Error finding start and end delmieters for %searchStop% in catMyChunk routine
exit /B 1
)
setlocal DisableDelayedExpansion
for /f "usebackq skip=%startLine% delims=" %%a in (`"findstr /n ^^ %~dpnx0"`) do (
set "oneLine=%%a"
setlocal EnableDelayedExpansion
set "oneLine=!oneLine:*:=!"
set /a linesLeftToRead-=1
if !linesLeftToRead! LEQ 0 exit /B
echo(!oneLine!>>%outFile%
)
goto: EOF
So my requirement is that the chunk of text is output literally without any changes whatsoever (i.e. I don't want to have to escape blank lines, %, !, <, etc.). This code is doing almost everything I need, except I haven't found a way to get the exclamation points output properly. Here is the output I get, which isn't quite right:
This is my test file
Hope you like it.
<got these>
% and these %
these too
yeah
Edit:
For anyone wanting the modified version of the subroutine that now works, here it is:
:catMyChunk
::Should call this function with 2 args, MYDELIM and outFile.txt
::where is to be catted to outFile.txt
::and text starts with <beginning of line>goto:MYDELIM
::and ends with <beginning of line>:MYDELIM
set searchStart=goto:%~1
set searchStop=:%~1
set outFile=%~2
set startLine=0
set endLine=0
for /f "delims=:" %%a in ('findstr -b -n !searchStart! %~dpnx0') do set "startLine=%%a"
for /f "delims=:" %%a in ('findstr -b -n !searchStop! %~dpnx0') do set "endLine=%%a"
set /a linesLeftToRead=%endLine% - %startLine%
del %outFile%
if "%linesLeftToRead%" LEQ "0" (
echo Error finding start and end delmieters for %searchStop% in catMyChunk routine
exit /B 1
)
setlocal DisableDelayedExpansion
for /f "usebackq skip=%startLine% delims=" %%a in (`"findstr /n ^^ %~dpnx0"`) do (
set "oneLine=%%a"
set /a linesLeftToRead-=1
setlocal EnableDelayedExpansion
set "oneLine=!oneLine:*:=!"
if !linesLeftToRead! LEQ 0 exit /B
echo(!oneLine!>>%outFile%
endlocal
)
endlocal
goto: EOF
Your code is missing a single endlocal in your FOR-loop.
You will then create for each loop a new local-context through the setlocal EnableDelayedExpansion, this will explode with some more lines in your text file.
Also, to preserve the exclamation marks (and also the carets) you need the toggling technique:
DOS batch files: How to read a file?
setlocal DisableDelayedExpansion
for /f "usebackq skip=%startLine% delims=" %%a in (`"findstr /n ^^ %~dpnx0"`) do (
set "oneLine=%%a"
setlocal EnableDelayedExpansion
set "oneLine=!oneLine:*:=!"
set /a linesLeftToRead-=1
if !linesLeftToRead! LEQ 0 exit /B
echo(!oneLine!>>%outFile%
endlocal
)
+1, Interesting application! I modified your code for a simpler and faster version:
#echo off
call :catMyChunk myCustomText see.txt
exit /b
goto:myCustomText
This is my test file
Hope you like it.
<got these>
% and these %
! these too
yeah
:myCustomText
:catMyChunk
::Should call this function with 2 args, MYDELIM and outFile.txt
::where is to be catted to outFile.txt
::and text starts with <beginning of line>goto:MYDELIM
::and ends with <beginning of line>:MYDELIM
setlocal DisableDelayedExpansion
set searchStart=goto:%~1
set searchStop=:%~1
set outFile=%~2
if exist %outFile% del %outFile%
set copyFlag=No
echo No> copyFlag
for /f "delims=" %%a in (%~f0) do (
set "oneLine=%%a"
setlocal EnableDelayedExpansion
if !copyFlag! == No (
if !oneLine! == %searchStart% echo Yes> copyFlag
) else (
if !oneLine! == %searchStop% (
echo No> copyFlag
) else (
echo/!oneLine!>> %outFile%
)
)
endlocal
set /p copyFlag=< copyFlag
)
endlocal
goto :eof
I also created another version that looks more like the Linux version, that is, the lines to copy are placed directly after invoking the routine, and the execution continue after the last copied line. Of course, to make this possible the routine is not invoked via call, but entered with a goto, and when the routine ends it execute a goto %MYDELIM% instead of a "return" (exit /b or goto :eof). Also, because a goto can not have parameters, the "parameters" are defined in variables before the invocation.
#echo off
set searchStop=EndOfMyText
set outFile=see.txt
goto :catMyChunk EndOfMyText
This is my test file
Hope you like it.
<got these>
% and these %
! these too
yeah
:EndOfMyText
exit /b
:catMyChunk
::Before JUMP to this "function" define 2 vars: searchStop and outFile
::where is to be catted to %outFile%
::and text starts with goto :catMyChunk %searchStop%
::and ends with :%searchStop%
setlocal DisableDelayedExpansion
set searchStart=goto :catMyChunk %searchStop%
if exist %outFile% del %outFile%
set copyFlag=No
echo No> copyFlag
for /f "delims=" %%a in (%~f0) do (
set "oneLine=%%a"
setlocal EnableDelayedExpansion
if !copyFlag! == No (
if /I !oneLine! == !searchStart! echo Yes> copyFlag
) else (
if !oneLine! == :%searchStop% (
echo No> copyFlag
) else (
echo/!oneLine!>> %outFile%
)
)
endlocal
set /p copyFlag=< copyFlag
)
endlocal
goto %searchStop%
EDIT
This new version is even faster and now works with all special cases, including empty lines:
:catMyChunk
::Should call this function with 2 args, MYDELIM and outFile.txt
::where is to be catted to outFile.txt
::and text starts with <beginning of line>goto:MYDELIM
::and ends with <beginning of line>:MYDELIM
setlocal EnableDelayedExpansion
set searchStart=goto:%~1
set searchStop=:%~1
set outFile=%~2
if exist %outFile% del %outFile%
findstr /n ^^ "%~f0" > pipeline.txt
call :seekMyChunk < pipeline.txt
del pipeline.txt
exit /B
:seekMyChunk
set oneLine=:EOF
set /P oneLine=
if !oneLine! == :EOF goto startNotFound
set oneLine=!oneLine:*:=!
if not !oneLine! == %searchStart% goto seekMyChunk
:catNextLine
set oneLine=:EOF
set /P oneLine=
if !oneLine! == :EOF goto stopNotFound
set oneLine=!oneLine:*:=!
if !oneLine! == %searchStop% goto :eof
echo/!oneLine!>> %outFile%
goto catNextLine
:startNotFound
echo Error finding start delimiter for %searchStart% in catMyChunk
goto :eof
:stopNotFound
echo Error finding stop delimiter for %searchStop% in catMyChunk
goto :eof