This question already has an answer here:
add multiple lines in middle of txtfile
(1 answer)
Closed 8 years ago.
ok here a file txt.txt
line1
line2
add after this line blah blah blah
line4
etc
etc
i want to add a lines after add after this line but i dont know what comes in the same line after add after this line
what i want to know is what all changes i have to make in [this] code
#ECHO OFF
SETLOCAL
SET /p info="enter info : "
:: read addafter line
(
FOR /f "delims=" %%i IN (poison1.txt) DO (
SET addafter=%%i
FOR /f "delims=" %%n IN (' findstr /n "^" txtfile.txt') DO (
SET line=%%n
SETLOCAL ENABLEDELAYEDEXPANSION
SET line=!line:*:=!
ECHO(!line!
IF "!line!"=="!addafter!" TYPE your_multiline_addition.txt
ENDLOCAL
)
)
)>newfile.txt
FC newfile.txt txtfile.txt
GOTO :eof
any help is much appreciated.
dont know how to use wild cards in string manipulation
You know what your line contains - it's in !line!
You know what you want to find - it's in !addafter!
So - to find whether !addafter! is in !line! all you need to do is
echo !line!|findstr "!addafter!" >nul
if errorlevel 1 (echo not found) else (echo found)
So read the documentation shown by
findstr /?
and work out what you need to find "beginining" or "ending" with ... , whether or not you need case-insensitivity and whether you need to use you search-for-me-string as a literal or a "regular expression" (noting that by default REGULAR EXPRESSION is assumed) and whether or not you want to *C*ombine "a string with spaces" or search for "any word in a set" without *C*ombining them together as a single string.
Related
I've been trying to figure out how to replace an entire line in a text file that contains a certain string using a Batch Script. I've found this solution provided by another user on Stack Overflow, which does the job, however, it just stops iterating through the text file at some random point and in turn, the output file is left with a bunch of lines untransferred from the original file. I've looked character by character, and line by line of the script to figure out what each part exactly does, and can not seem to spot what is causing this bug.
The code provided, thanks to Ryan Bemrose on this question
copy nul output.txt
for /f "tokens=1* delims=:" %%a in ('findstr /n "^" file.txt') do call :do_line "%%b"
goto :eof
:do_line
set line=%1
if {%line:String =%}=={%line%} (
echo.%~1 >> output.txt
goto :eof
)
echo string >> output.txt
The lines it is stopping at always either contain < or > or both and lines with | will either cause it to stop, or sometimes it will delete the line and continue.
To do this robustly, Delayed expansion is necessary to prevent "poison" characters such as < > & | etc being interpreted as command tokens.
Note however that delayed expansion should not be enabled until after the variable containing the line value is defined so as to preserve any ! characters that may be present.
The following will robustly handle all Ascii printable characters *1, and preserve empty lines present in the source file:
#Echo off
Set "InFile=%~dp0input.txt"
Set "OutFile=%~dp0output.txt"
Set "Search=String "
Set "Replace="
>"%OutFile%" (
for /F "delims=" %%G in ('%SystemRoot%\System32\findstr.exe /N "^" "%InFile%"') do (
Set "line=%%G"
call :SearchReplace
)
)
Type "%OutFile%" | More
goto :eof
:SearchReplace
Setlocal EnableDelayedExpansion
Set "Line=!Line:*:=!"
If not defined Line (
(Echo()
Endlocal & goto :eof
)
(Echo(!Line:%Search%=%Replace%!)
Endlocal & goto :eof
*1 Note - Due to how substring modification operates, You cannot replace Search strings that:
contain the = Operator
Begin with ~
I have created command script for reading %N% lines from file. The problem is I can't delete " from anywhere in all text streams when I work with file's text. " deletion is very needed because if file's text line have substring like "text" and text have special chars or even worse, script code, then the script crashes or works not proper way (including script control capturing by programmer who specially composed the text).
If I can't delete " from the text stream(s), then I just want to identify, that the file (or it's first %N% lines, including empty lines) contains at least one " char.
Any thoughts are appreciated, including any file preprocessing. But main aim is script speed.
for /f "skip=2 delims=" %%a in ('find /v /n "" "file" 2^>nul') do set "v=%%a"&call :v&if not errorlevel 1 goto FURTHER1
goto FURTHER2
:v
for /f "delims=[]" %%a in ("%v%") do set "line%%a=%v:*]=%"&if %%a lss %N% (exit /b 1) else exit /b 0
#ECHO Off
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q39558311.txt"
SET "tempfilename1=%sourcedir%\q39558311#.txt"
>"%tempfilename1%" ECHO("
SET /a linefound=0
FOR /f "tokens=1 delims=:" %%a IN ('findstr /n /g:"%tempfilename1%" "%filename1%"') DO (
IF %%a gtr 2 SET /a linefound=%%a&GOTO report
)
:report
ECHO quote found AT line %linefound%
DEL "%tempfilename1%"
GOTO :EOF
You would need to change the setting of sourcedir and filename1 to suit your circumstances.
tempfile1 can be any name - it's just a temporary file; I chose that particular name for convenience.
I used a file named q39558311.txt containing some dummy data for my testing.
Essentially, create a file containing a single quote on a single line *tempfile1) then use findstr with the /g:filename option to read in the target strings to find. When findstr finds the line, it numbers it and outputs line_number:line found. Using : as a delimiter, token 1 of this line is the line number.
I don't understand why you've used the skip=number in your code. Do you intend to skip testing the first 2 lines of the target file?
the IF %%a gtr 2 tests the line number found. If it is greater than 2, then the variable linefound is set and the for loop is terminated.
I chose to initialise linefound to zero. It will remain zero if no " is found in lines 2..end. Equally, you could clear it and then it will be defined (with a value of first-line-found-with-quote-greater than-2) and no defined on not found.
I can only identify ", but not delete. Waiting for your suggestions on it!
>nul 2>&1 findstr /m \" "file"
if not errorlevel 1 echo double quote found!
Using a .bat script, I want to find a line that says # Site 1 and replace the text in the next line with a variable. I found tutorials on StackOverflow for finding and replacing a line, but not finding a line and replacing the next line. Any help?
#echo off
set "the_file=C:\someFile"
set "search_for=somestring"
set "variable=http://site1"
for /f "tokens=1 delims=:" %%# in ('findstr /n /c:"%search_for%" "%the_file%"') do (
set "line=%%#"
goto :break
)
:break
set /a lineBefore=line-1
set /a nextLine=line+1
break>"%temp%\empty"&&fc "%temp%\empty" "%the_file%" /lb %lineBefore% /t |more +4 | findstr /B /E /V "*****" >newFile
echo %variable%>>newFile
more "%the_file%" +%nextLine% 1>>newFile
echo move /y newFile "%the_file%"
Check if newFile is ok and remove the echo at the front of the last line.
you need to set the three variables at the beginning by yourself.Have on mind that more command sets spaces instead of tabs
#ECHO OFF
SETLOCAL
SET "filename=q28567045.txt"
SET "afterme=# Site 1"
SET "putme=put this line after # Site 1"
SET "skip1="
(
FOR /f "usebackqdelims=" %%a IN ("%filename%") DO (
IF DEFINED skip1 (ECHO(%putme%) ELSE (ECHO(%%a)
SET "skip1="
IF /i "%%a"=="%afterme%" SET skip1=y
)
)>newfile.txt
GOTO :EOF
Produces newfile.txt
The flag `skip1 to skip the line is first reset, then the file is read line by line.
If the skip1 flag is set, then the replacement line is echoed in place of the line read; if not, the line read is echoed.
Then the skip1 flag is cleared
If the line read to %%a matches the string assigned to afterme then the flag skip1 is set (to y - but it doesn't matter what the value is)
Note that empty lines and those starting ; will be ignored and not reproduced - this is standard behaviour of for /f.
If you want to replce the starting file, then simply add
move /y newfile.txt "%filename%"
before the goto :eof line.
Even though I enjoy working with batch, I generally avoid using pure native batch to edit text files because a robust solution is usually complicated and slow.
This can be done easily and efficiently using JREPL.BAT - a hybrid JScript/batch utility that performs regular expression replacement. JREPL.BAT is pure script that runs natively on any Windows machine from XP onward.
#echo off
setlocal
set "newVal=Replacement value"
call jrepl "^.*" "%newValue%" /jbeg "skip=true" /jendln "skip=($txt!='# Site 1')" /f test.txt /o -
The /F option specifies the file to process
The /O option with value of - specifies to replace the original file with the result.
The /JBEG option initializes the command to skip (not replace) each line.
The /JENDLN option checks the value of each line just before it is written out, and sets SKIP off (false) if it matches # Site 1. The next line will be replaced only when SKIP is false.
The search string matches an entire line.
The replacement string is your value stored in a variable.
This problem is similar to this one and may use an equivalent solution. The pure Batch file solution below should be the fastest one of its kind.
#echo off
setlocal EnableDelayedExpansion
set "search=# Site 1"
set "nextLine=Text that replaces next line"
rem Get the line number of the search line
for /F "delims=:" %%a in ('findstr /N /C:"%search%" input.txt') do set /A "numLines=%%a-1"
rem Open a code block to read-input-file/create-output-file
< input.txt (
rem Read the first line
set /P "line="
rem Copy numLines-1 lines
for /L %%i in (1,1,%numLines%) do set /P "line=!line!" & echo/
rem Replace the next line
echo %nextLine%
rem Copy the rest of lines
findstr "^"
) > output.txt
rem Replace input file with created output file
move /Y output.txt input.txt > NUL
This method will fail if the input file have empty lines and also have other limitations.
For a further description of this method, see this post.
I'm trying to make a batch file which checks if the user input does exist in xy.txt well thats easy
but now if the user input is "hello world" i want to check each word individually.
i tried that..
#setlocal enableextensions enabledelayedexpansion
#echo off
:start
set /p word=" "
for /F "tokens=* delims= " %%A in ("%word%") do set A=%%A & set B=%%B
if %A%=="" goto Anovalue
if not %A%=="" goto checkforA
:Anovalue
echo first word has no value
pause
if %B%=="" goto Bnovalue
if not %A%=="" goto checkforB
:Bnovalue
echo second word has no value
pause
goto start
:checkforA
findstr /c:"%A%" xy.txt > NUL
if ERRORLEVEL 1 goto notexistA
if ERRORLEVEL 2 goto existA
:checkforB
findstr /c:"%B%" xy.txt > NUL
if ERRORLEVEL 1 goto notexistB
if ERRORLEVEL 2 goto existB
:existA
echo first word does exist in xy.txt
pause
goto checkforB
:existB
echo second word does exist in xy.txt
pause
goto start
:notexistA
echo first word does not exist in xy.txt
pause
(echo %A%) >>xy.txt
goto checkforB
:notexistB
echo second word does not exist in xy.txt
pause
(echo %B%) >>xy.txt
goto start\
Couldn't I do that in a more easier and smarter way?
There are a lot of ways to do what you are asking to do, many of which use a lot less code. For instance, given the following file xy.txt:
this is a test of the
system to see if it
will work the way
that i want it to
work today
This batchfile (check.bat):
#echo off
setlocal ENABLEDELAYEDEXPANSION
set words=%1
set words=!words:"=!
for %%i in (!words!) do findstr /I /C:"%%i" xy.txt > NUL && echo Found - %%i || echo Not Found - %%i
endlocal
Well return the following:
c:\>check "is test smart"
Found - is
Found - test
Not Found - smart
However, words within a word will also return true. For instance, check "day" will find day, even though it is not a separate word because it is part of today. Handling that situation would be a little more tricky. To do that, you need to encapsulate the search words with some character, and then replace all the spaces in xy.txt with the same encapsulation character. For instance, if we use a ., replace all spaces in xy.txt whwith the ., and then search for .word., we will find only whole words that match.
#echo off
setlocal ENABLEDELAYEDEXPANSION
set words=%1
set words=!words:"=!
set words=.!words: =. .!.
for /f "tokens=* delims=" %%i in (xy.txt) do (
set line=%%i
set line=.!line: =.!.
echo !line!>>xy.txt.tmp
)
for %%i in (!words!) do (
set word=%%i
set word=!word:.=!
findstr /I /C:"%%i" xy.txt.tmp > NUL && echo Found - !word! || echo Not Found - !word!
)
del xy.txt.tmp
endlocal
I chose to create an intermediary file xy.txt.tmp to house the edited file where the spaces are replaced with .. Then we can execute the following command and get the displayed results:
c:\>check "this is a test of the stem today that will work each day"
Found - this
Found - is
Found - a
Found - test
Found - of
Found - the
Not Found - stem
Found - today
Found - that
Found - will
Found - work
Not Found - each
Not Found - day
It correctly finds words at the beginning of the line, end of the line and anywhere in between. The only downside is the intermediate file that it creates and then deletes. Doing it without an intermediate file would be a bit more complex...
Task in CMD.
1) How can I compare if string is in string? I checked manual here for "Boolean Test "does string exist ?"" But I can't understand the example or it does not work for me. This piece of code, it is just a try. I try to make a string compare of filter some sting if there is a tag <a> in a line.
FOR /f "tokens=* delims= usebackq" %%c in ("%source%") DO (
echo %%c
IF %%c == "<a" (pause)
)
So while I read a file, it should be paused if there is a link on a line.
2) I have one more ask. I would need to filter the line if there is a specific file in the link, and get content of the link. My original idea was to try to use findstr with regex, but it seems not to use sub-patterns. And next problem would be how to get the result to variable.
set "pdf=0_1_en.pdf"
type "%source%" | grep "%pdf%" | findstr /r /c:"%pdf%.*>(.*).*</a>"
So in summary, I want to go through file and if there is a link like this: REPAIRED: *
<b>GEN 0.1 Preface</b>
I forgot to style this as a code, so the inside of code was not displayed. Sorry.
Warnning: we don't know the path, only the basic filename.
Get the title GEN 0.1 Preface. But you should know, that there are also similar links with same link, which contain image, not a text inside a tag.
Code according Aacini to be changed a little bit:
#echo off
setlocal EnableDelayedExpansion
set "source=GEN 0 GENERAL.html"
set "pdf=0_1_en.pdf"
echo In file:%source%
echo Look for anchor:%pdf%
rem Process each line in %source% file:
for /F "usebackq delims=" %%c in ("%source%") do (
set "line=%%c"
rem Test if the line contain a "tag" that start with "<a" string:
set "tag=!line:*<a=!"
if not "!tag!" == "!line!" (
rem Take the string in tag that end in ">"
for /F "delims=^>" %%a in ("!tag!") do set "link=%%a"
echo Link found: !link!
if "!link!" == "GEN 0.1 Preface" echo Seeked link found
)
)
pause
Still not finished
Although your question is extensive it does not provide to much details, so I assumed several points because I don't know too much about .PDF files, tags, etc.
#echo off
setlocal EnableDelayedExpansion
set "source=GEN 0 GENERAL.html"
set "pdf=0_1_en.pdf"
echo In file: "%source%"
echo Look for anchor: "%pdf%"
rem Process each line in %source% file:
for /F "usebackq delims=" %%c in ("%source%") do (
set "line=%%c"
rem Test if the line contain "<a>" tag:
set "tag=!line:*<a>=!"
if not "!tag!" == "!line!" (
rem Test if "<a>" tag contain the anchor pdf file:
if not "!tag:%pdf%=!" == "!tag!" (
rem Get the value of "<b>" sub-tag
set "tag=!tag:<b>=$!"
set "tag=!tag:</b>=$!"
for /F "tokens=2 delims=$" %%b in ("!tag!") do set title=%%b
echo Title found: "!title!"
)
)
)
pause
Any missing point can be added or fixed, if you give me precise details about them.
EDIT: I fixed the program above after last indications from the OP. I used $ character to get the Title value; if this character may exist in original Tag, it must be changed by another unused one.
I tested this program with this "GEN 0 GENERAL.html" example file:
Line one
<a>href="/Dokumenter/EK_GEN_0_X_en.pdf" class="uline"><b>GEN 0.X Preface</b></a>
Line three
<a>href="/Dokumenter/EK_GEN_0_1_en.pdf" class="uline"><b>GEN 0.1 Preface</b></a>
Line five
and get this result:
In file: "GEN 0 GENERAL.html"
Look for anchor: "0_1_en.pdf"
Title found: "GEN 0.1 Preface"
EDIT: New faster method added
There is a simpler and faster method to solve this problem that, however, may fail if a line contains more than one tag:
#echo off
setlocal EnableDelayedExpansion
set "source=GEN 0 GENERAL.html"
set "pdf=0_1_en.pdf"
echo In file: "%source%"
echo Look for anchor: "%pdf%"
for /F "delims=" %%c in ('findstr /C:"<a>" "%source%" ^| findstr /C:"%pdf%"') do (
set "tag=%%c"
rem Get the value of "<b>" sub-tag
set "tag=!tag:<b>=$!"
set "tag=!tag:</b>=$!"
for /F "tokens=2 delims=$" %%b in ("!tag!") do set title=%%b
echo Title found: "!title!"
)
pause
First, one important question: does this really have to be implemented via a CMD script? Would you be able to go with VBScript, PowerShell, C#, or some other scripting/programming language? CMD is a notoriously painful scripting environment.
Secondly, I'm not sure if this answers your question--it's a bit unclear--but here's a quick trick you can use to see in CMD to see if a given string contains another substring:
setlocal enableextensions enabledelayedexpansion
set PATTERN=somepattern
for /f "delims=" %%f in (somefile.txt) do (
set CURRENT_LINE=%%f
if "!CURRENT_LINE:%PATTERN%=!" neq "!TEMP!" (
echo Found pattern in line: %%f
)
)
The idea is that you try to perform string replacement and see if anything was changed. This is certainly a hack, and it would be preferable if you could instead use a tool like findstr or grep, but if you're limited in your options, something like the above should work.
NOTE: I haven't actually run the above script excerpt, so let me know if you have any difficulty with it.
I have modified the way to do it. I realized that it is better to find name of pdf document first. This is my almost completed solution, but I ask you if you could help me with the last point. The last replacing statement does not work because I need to remove closing tag b. Just to get the title.
#echo off
setlocal EnableDelayedExpansion
set "source=GEN 0 GENERAL.html"
set "pdf=0_1_en.pdf"
echo In file:%source%
echo Look for anchor:%pdf%
rem Process each line in %source% file:
for /F "usebackq delims=" %%c in ("%source%") do (
set "line=%%c"
REM Test if the line contains pdf file I look for:
SET "pdfline=!line:%pdf%=!"
if not "!pdfline!" == "!line!" (
cls
echo Line: !line!
REM Test if the pdfline contains tag b
SET "tagline=!pdfline:*><b>=!"
if not "!tagline!" == "!pdfline!" (
cls
echo ACTUAL LINE: !tagline!
REM Remove closing tag b
SET "title=!tagline:</b*=!"
echo TITLE: !title!
pause
)
)
)
pause
BTW:
The html page I work with is here.
So I ask you to help complete/repair line SET "title=!tagline:</b*=!"