i want to convert every whitespace in input to a new line character and save to a file (say tmp.txt) with batch file windows .
input:
http://www.example1.com wwwexample2com wwwexample3com wwwexample4com
to output in tmp.txt :
http://www.example1.com
wwwexample2com
wwwexample3com
wwwexample4com
how do I do that?
If the input is a file named "input file.txt" and the urls contain "=":
#echo off
setlocal enableDelayedExpansion
>"output file.txt" (for /f "usebackq delims=" %%a in ("input file.txt") do (
set line=%%a
call :listtokens "!line: =" "!"
))
pause & exit
:listtokens
if .%1==. (exit /b) else (echo %~1 & shift & goto listtokens)
If the input is a variable with alphanumeric words:
>"output file.txt" (for %%a in (%VARIABLE%) do echo %%a)
If the input is a file named "input file.txt" with alphanumeric words:
>"output file.txt" (for /f "usebackq delims=" %%a in ("input file.txt") do (
for %%b in (%%a) do echo %%b
))
If it's from a console utility that outputs alphanumeric words:
>"output file.txt" (for /f "delims=" %%a in ('run some command') do (
for %%b in (%%a) do echo %%b
))
The following pure batch script will put each space delimited "word" onto a separate line in the output. Empty lines will be stripped. The script is very robust. It should handle any ASCII text as long as every source line is <8kb. Note this will not convert other whitespace characters like tab into newlines.
#echo off
setlocal disableDelayedExpansion
>"input.txt.new" (
for /f "usebackq eol= tokens=* delims= " %%A in ("input.txt") do (
set "ln=%%A"
setlocal enableDelayedExpansion
echo(!ln: =^
!%= This line and the empty line above must remain exactly as written=%
endlocal
)
)
findstr . "input.txt.new" >"output.txt"
del "input.txt.new"
type output.txt
However, I would not use the above because I think pure batch makes text manipulation overly complex.
I would use a regular expression text processing utility called JREPL.BAT. It is pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward. It is much simpler, faster, and more robust than any pure batch solution. The utility is extensively documented, and there are many regular expression tutorials available on the web.
The following one liner will efficiently put each whitespace delimtted "word" onto a separate line in the output.
jrepl "\S+" "$0" /jmatch /f "input.txt" /o "output.txt"
If you really want to convert every whitespace character into a newline, as you say in your comment, then you could use the following. But I don't think it is really what you want.
jrepl "\s" "\n" /x /f "input.txt" /o "output.txt"
Related
Currently my code is: findstr Starfy ./List.txt > result.txt
My result.txt is
3841 - Legendary Starfy, The (USA).zip
x166 - Legendary Starfy, The (USA) (Demo) (Kiosk).zip
However, I want result 1 and result 2 to have their own seperate files, so it would look like:
result1.txt > 3841 - Legendary Starfy, The (USA).zip
result2.txt > x166 - Legendary Starfy, The (USA) (Demo) (Kiosk).zip
I'm unsure how to make this work, and would love if someone is able to help point me in the right direction.
This works:
#echo off
for /F "tokens=1* delims=:" %%a in ('findstr "Starfy" .\List.txt ^| findstr /N "^"') do >result%%a.txt echo %%b
Just pass your original results into another instance of findstr /N command that add line numbers. After that, separate the number and the line in a for /F command and output each line to its corresponding numbered file...
for /f "tokens=1,* delims=:" %%S in ('findstr /i "echo" "%~f0"^|findstr /n /i "echo" ') do ECHO %%T>"U:\moreresults\result%%S.txt"
The command quoted in parentheses finds a string (in this case, echo) ignoring case (/i) within the file "%~f0" (this batch file, which contains a heap of standard code I use for testing). This is passed to another instance of findstr, this time looking for the same string, but numbering the lines (as serialnumber:linetext).
The resultant text is tokenised using : as a separator, so %%S receives the serialnumber and %%T receives the rest of the line (token *). Then simply build the result filename using %%S and write the text part of the line to it.
The caret is used to escape the pipe so that cmd knows that the pipe is part of the command-to-be-executed, not of the for command.
Assuming that you do not already have files in the location you're outputting your results, which could alalready be named using that intended naming scheme, then something like this may suit you:
#Echo Off
SetLocal EnableExtensions EnableDelayedExpansion
Set "i=0"
For /F Delims^=^ EOL^= %%G In (
'%SystemRoot%\System32\find.exe /I "Starfy" 0^<".\List.txt" 2^>NUL'
) Do (
Set /A i += 1
1>"Result!i!.txt" Echo %%G
)
Please note that I used find.exe instead of findstr.exe simply because your example used a simple string containing a series of alphabetic only characters. Feel free to change it to '%SystemRoot%\System32\findstr.exe /LIC:"Starfy" ".\List.txt" 2^>NUL', or similar, should you require a more specialized matching mechanism.
I am trying to write a Windows batch script which examines an XML file (the iml file) to search for a certain line, . I am having trouble with the spaces in the string. Is there a way to escape or compensate for the spaces?
for /f "tokens=*" %%a in (abcd.iml) do (
echo %%a
if %%a==^<orderEntry type="inheritedJdk" ^> (echo 'FOUND')
)
Put the %%a in quotes so it is like "%%a." Instead of using the "==" operator to compare %%a and "^" it would be better to use the EQU comparator so the final code would look like:
for /f "tokens=*" %%a in (abcd.iml) do (
echo %%a
if "%%a" EQU "<orderEntry type="inheritedJdk" >" (echo 'FOUND')
)
For more information on EQU and other operators see https://ss64.com/nt/if.html or https://ss64.com/nt/equ.html
no need for a for loop. A simple findstr is much faster:
findstr /c:"<orderEntry type=\"inheritedJdk\" >" "abcd.iml" >nul && echo found || echo nope
Note: the quotes within the string have to be escaped (escape character for findstr is a backslash)
This DOS batch script is stripping out the blank lines and not showing the blank lines in the file even though I am using the TYPE.exe command to convert the file to make sure the file is ASCII so that the FIND command is compatible with the file. Can anyone tell me how to make this script include blank lines?
#ECHO off
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE.exe "build.properties" ^| FIND.exe /V ""`) DO (
ECHO --%%A--
)
pause
That is the designed behavior of FOR /F - it never returns blank lines. The work around is to use FIND or FINDSTR to prefix the line with the line number. If you can guarantee no lines start with the line number delimiter, then you simply set the appropriate delimiter and keep tokens 1* but use only the 2nd token.
::preserve blank lines using FIND, assume no line starts with ]
::long lines are truncated
for /f "tokens=1* delims=]" %%A in ('type "file.txt" ^| find /n /v ""') do echo %%B
::preserve blank lines using FINDSTR, assume no line starts with :
::long lines > 8191 bytes are lost
for /f "tokens=1* delims=:" %%A in ('type "file.txt" ^| findstr /n "^"') do echo %%B
::FINDSTR variant that preserves long lines
type "file.txt" > "file.txt.tmp"
for /f "tokens=1* delims=:" %%A in ('findstr /n "^" "file.txt.tmp"') do echo %%B
del "file.txt.tmp"
I prefer FINDSTR - it is more reliable. For example, FIND can truncate long lines - FINDSTR does not as long as it reads directly from a file. FINDSTR does drop long lines when reading from stdin via pipe or redirection.
If the file may contain lines that start with the delimiter, then you need to preserve the entire line with the line number prefix, and then use search and replace to remove the line prefix. You probably want delayed expansion off when transferring the %%A to an environment variable, otherwise any ! will be corrupted. But later within the loop you need delayed expansion to do the search and replace.
::preserve blank lines using FIND, even if a line may start with ]
::long lines are truncated
for /f "delims=" %%A in ('type "file.txt" ^| find /n /v ""') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*]=!"
echo(!ln!
endlocal
)
::preserve blank lines using FINDSTR, even if a line may start with :
::long lines >8191 bytes are truncated
for /f "delims=*" %%A in ('type "file.txt" ^| findstr /n "^"') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
echo(!ln!
endlocal
)
::FINDSTR variant that preserves long lines
type "file.txt" >"file.txt.tmp"
for /f "delims=*" %%A in ('findstr /n "^" "file.txt.tmp"') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
echo(!ln!
endlocal
)
del "file.txt.tmp"
If you don't need to worry about converting the file to ASCII, then it is more efficient to drop the pipe and let FIND or FINDSTR open the file specified as an argument, or via redirection.
There is another work around that completely bypasses FOR /F during the read process. It looks odd, but it is more efficient. There are no restrictions with using delayed expansion, but unfortunately it has other limitations.
1) lines must be terminated by <CR><LF> (this will not be a problem if you do the TYPE file conversion)
2) lines must be <= 1021 bytes long (disregarding the <CR><LF>)
3) any trailing control characters are stripped from each line.
4) it must read from a file - you can't use a pipe. So in your case you will need to use a temp file to do your to ASCII conversion.
setlocal enableDelayedExpansion
type "file.txt">"file.txt.tmp"
for /f %%N in ('find /c /v "" ^<"file.txt.tmp"') do set cnt=%%N
<"file.txt.tmp" (
for /l %%N in (1 1 %cnt%) do(
set "ln="
set /p "ln="
echo(!ln!
)
)
del "file.txt.tmp"
I wrote a very simple program that may serve as replacement for FIND and FINDSTR commands when they are used for this purpose. My program is called PIPE.COM and it just insert a blank space in empty lines, so all the lines may be directly processed by FOR command with no further adjustments (as long as the inserted space don't cares). Here it is:
#ECHO off
if not exist pipe.com call :DefinePipe
FOR /F "USEBACKQ delims=" %%A IN (`pipe ^< "build.properties"`) DO (
ECHO(--%%A--
)
pause
goto :EOF
:DefinePipe
setlocal DisableDelayedExpansion
set pipe=´)€ì!Í!ŠÐŠà€Ä!€ü.t2€ü+u!:æu8²A€ê!´#€ì!Í!².€ê!´#€ì!Í!²+€ê!´#€ì!Í!Šò€Æ!´,€ì!Í!"Àu°´LÍ!ëÒ
setlocal EnableDelayedExpansion
echo !pipe!>pipe.com
exit /B
EDIT: Addendum as answer to new comment
The code at :DefinePipe subroutine create a 88 bytes program called pipe.com, that basically do a process equivalent to this pseudo-Batch code:
set "space= "
set line=
:nextChar
rem Read just ONE character
set /PC char=
if %char% neq %NewLine% (
rem Join new char to current line
set line=%line%%char%
) else (
rem End of line detected
if defined line (
rem Show current line
echo %line%
set line=
) else (
rem Empty line: change it by one space
echo %space%
)
)
goto nextChar
This way, empty lines in the input file are changed by lines with one space, so FOR /F command not longer omit they. This works "as long as the inserted space don't cares" as I said in my answer.
Note that the pipe.com program does not work in 64-bits Windows versions.
Antonio
Output lines including blank lines
Here's a method I developed for my own use.
Save the code as a batch file say, SHOWALL.BAT and pass the source file as a command line parameter.
Output can be redirected or piped.
#echo off
for /f "tokens=1,* delims=]" %%a in ('find /n /v "" ^< "%~1"') do echo.%%ba
exit /b
EXAMPLES:
showall source.txt
showall source.txt >destination.txt
showall source.txt | FIND "string"
An oddity is the inclusion of the '^<' (redirection) as opposed to just doing the following:
for /f "tokens=1,* delims=]" %%a in ('find /n /v "" "%~1"') do echo.%%ba
By omitting the redirection, a leading blank line is output.
Thanks to dbenham, this works, although it is slightly different than his suggestion:
::preserve blank lines using FIND, no limitations
for /f "USEBACKQ delims=" %%A in (`type "file.properties" ^| find /V /N ""`) do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*]=!"
echo(!ln!
endlocal
)
As mentioned in this answer to the above question, it doesn't seem that lines are skipped by default using for /f in (at least) Windows XP (Community - Please update this answer by testing the below batch commands on your version & service pack of Windows).
EDIT: Per Jeb's comment below, it seems that the ping command, in at least Windows XP, is
causing for /f to produce <CR>'s instead of blank lines (If someone knows specifically why, would
appreciate it if they could update this answer or comment).
As a workaround, it seems that the second default delimited token (<space> / %%b in the example)
returns as blank, which worked for my situation of eliminating the blank lines by way of an "parent"
if conditional on the second token at the start of the for /f, like this:
for /f "tokens=1,2*" %%a in ('ping -n 1 google.com') do (
if not "x%%b"=="x" (
{do things with non-blank lines}
)
)
Using the below code:
#echo off
systeminfo | findstr /b /c:"OS Name" /c:"OS Version"
echo.&echo.
ping -n 1 google.com
echo.&echo.
for /f %%a in ('ping -n 1 google.com') do ( echo "%%a" )
echo.&echo.&echo --------------&echo.&echo.
find /?
echo.&echo.
for /f %%a in ('find /?') do ( echo "%%a" )
echo.&echo.
pause
.... the following is what I see on Windows XP, Windows 7 and Windows 2008, being the only three versions & service packs of Windows I have ready access to:
I'm trying to insert a line into a file using the following code (from Write batch variable into specific line in a text file)
#echo off
setlocal enableextensions enabledelayedexpansion
set inputfile=variables.txt
set tempfile=%random%-%random%.tmp
copy /y nul %tempfile%
set line=0
for /f "delims=" %%l in (%inputfile%) do (
set /a line+=1
if !line!==4 (
echo WORDS YOU REPLACE IT WITH>>%tempfile%
) else (
echo %%l>>%tempfile%
)
)
del %inputfile%
ren %tempfile% %inputfile%
endlocal
My problem is the file has comment lines (which start with semicolons) which need to be kept
; directory during network startup. This statement must indicate a local disc
; drive on your PC and not a network disc drive.
LOCALDRIVE=C:\TEMP;
; PANELISATION PART/NET NAMING CONVENTION
; When jobs are panelised, parts/nets are renamed for each panel step by
When I run the batch file, it ignores the semicolon lines, So I only get:
LOCALDRIVE=C:\TEMP;
What do I need to do to keep the semicolon lines?
The EOL option determines what lines are to be ignored. The default value is a semicolon. If you know a character that can never appear in the first position of a line, then you can simply set EOL to that character. For example, if you know a line can't start with |, then you could use
for /f "eol=| delims=" %%l in (%inputfile%) do ...
There is an awkward syntax that disables EOL completely, and also disables DELIMS:
for /f delims^=^ eol^= %%l in (%inputfil%) do ...
Note that FOR /F always discards empty lines, so either of the above would result in:
; directory during network startup. This statement must indicate a local disc
; drive on your PC and not a network disc drive.
LOCALDRIVE=C:\TEMP;
; PANELISATION PART/NET NAMING CONVENTION
; When jobs are panelised, parts/nets are renamed for each panel step by
A trick is used if you want to preserve empty lines. Use FIND or FINDSTR to insert the line number before each line, and then use expansion find/replace to remove the line number. Now you know the line never begins with ;, so you can ignore the EOL option.
for /f "delims=" %%L in ('findstr /n "^" "%inputfile%"') do (
set "ln=%%L"
set "ln=!ln:*:=!"
REM You now have the original line, do whatever needs to be done here
)
But all of the above have a potential problem in that you have delayed expansion enabled when you expand the FOR variable, which means that any content containing ! will be corrupted. To solve this you must toggle delayed expansion on and off within the loop:
setlocal disableDelayedExpansion
...
for /f "delims=" %%L in (findstr /n "^" "%inputfile%") do (
set "ln=%%L"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
REM You now have the original line with ! preserved, do whatever needs done here
endlocal
)
Also, when ECHOing an empty line, it will print out ECHO is off unless you do something like
echo(!ln!
It takes time to open and position the write cursor to the end every time you use >> within the loop. It is faster to enclose the entire operation in one set of parentheses and redirect once. Also, you can replace the DEL and REN with a single MOVE command.
Here is a final robust script:
#echo off
setlocal disableDelayedExpansion
set "inputfile=variables.txt"
set line=0
>"%inputfile%.new" (
for /f "delims=" %%L in (findstr /n "^" "%inputfile%") do (
set "txt=%%L"
set /a line+=1
setlocal enableDelayedExpansion
set "txt=!txt:*:=!"
if !line! equ 4 (
echo New line content here
) else (
echo(!txt!
)
endlocal
)
)
move /y "%inputfile%.new" "%inputfile%" >nul
endlocal
That is an awful lot of work for such a simple task, and it requires a lot of arcane knowledge.
There is a much quicker hack that works as long as
your first 4 lines do not exceed 1021 bytes
none of your first 3 lines have trailing control characters that need to be preserved
the remaining lines do not have <tab> characters that must be preserved (MORE converts <tab> into a string of spaces.
#echo off
setlocal enableDelayedExpansion
set "inputfile=variables.txt"
>"%inputfile%.new" (
<"%inputfile%" (
for /l %%N in (1 1 3) do (
set "ln="
set /p "ln="
echo(!ln!
)
)
echo New line content here
more +4 "%inputfile%"
)
move /y "%inputfile%.new" "%inputfile%"
That is still a lot of work and arcane knowledge.
I would use my JREPL.BAT utility
Batch is really a terrible tool for text processing. That is why I developed JREPL.BAT to manipulate text using regular expressions. It is a hybrid JScript/batch script that runs natively on any Windows machine from XP onward. It is extremely versatile, robust, and fast.
A minimal amount of code is required to solve your problem with JREPL. Your problem doesn't really require the regular expression capabilities.
jrepl "^" "" /jendln "if (ln==4) $txt='New content here'" /f "variables.txt" /o -
If used within a batch script, then you must use call jrepl ... because JREPL.BAT is also a batch script.
By default, the FOR command treats ; as the end-of-line character, so all those lines that start with ; are being ignored.
Add eol= to your FOR command, like this:
for /f "eol= delims=" %%l in (%inputfile%) do (
It looks like you're echoing just the line delimiter, not the whole line:
echo %%l>>%tempfile%
I'm rusty on ms-dos scripts, so I can't give you more than that.
I have a txt file with this format:
some text
another uninteresting line
// some more lines can come here
[ actually interesting
// this is the stuff I want
]
I want to be able to get everything between the square brackets [] (including the brackets themselves).
(since I know that there's no text after the closing bracket, it's enough to be able to delete just the first lines before the [ char).
I'm pretty sure I can do it with findStr, but not sure exactly how.
You can use VBScript. Save the following as extract.vbs
flag=0
Do While Not WScript.StdIn.AtEndOfStream
Line = WScript.StdIn.ReadLine()
If Left(Line,1)="[" Then flag=1 End If
If flag=1 Then
WScript.Stdout.WriteLine(Line)
End If
Loop
Then run
CSCRIPT /NOLOGO EXTRACT.VBS < YOURFILE
It sets a flag to zero, then reads the input file one line at a time till the end. If it encounters a line starting with "[" it sets flag=1. Then it prints every line it finds when flag is set to 1.
If you want to save the lines it finds, in a new file, run it like this:
CSCRIPT /NOLOGO EXTRACT.VBS < YOURFILE > NEWFILE
FINDSTR cannot solve this on its own.
Given your situation that you can simply delete all lines before the line that starts with [, all you need is the following native batch script.
#echo off
setlocal
for /f "delims=:" %%N in ('findstr /n [ "file.txt"') do if not defined N set /a N=%%N-1
set "skip="
if %N% gtr 1 set "skip=skip=%N%"
(for /f "usebackq %skip% delims=" %%A in ("file.txt") do echo %%A) >"newFile.txt"
If you know that your file does not contain tabs, or if it is OK that tabs are converted to a string of spaces, then it is even easier:
#echo off
setlocal
for /f "delims=:" %%N in ('findstr /n [ "file.txt"') do if not defined N set /a N=%%N-1
more +%N% "file.txt" >"newFile.txt"
The solution is a one liner if you use REPL.BAT - a hybrid JScript/batch utility that performs regular expression search and replace on stdin and writes the result to std out. It is pure script that will run natively on any modern Windows machine from XP onward.
Assuming that [ only appears once, then:
type "file.txt" | repl "[^[]*\[" "[" m >"newFile.txt"
It is even simple to support multiple blocks between square brackets where the [ and/or ] could be in the middle of a line:
type "file.txt" | repl "[^[]*(\[[\s\S]*?\])[^[]*" "$1\r\n" mx >"newFile.txt"
#echo off
setlocal enableextensions disabledelayedexpansion
set "dataFile=data.txt"
rem search the starting line
set "startLine="
for /f "tokens=1 delims=:" %%a in (
'findstr /l /b /n /c:"[" "%dataFile%"'
) do if not defined startLine set "startLine=%%a"
rem remove all lines before the starting one
if defined startLine for /f "tokens=1,* delims=:" %%a in (
'findstr /n "^" "%dataFile%" ^& break ^> "%dataFile%"'
) do if %%a geq %startLine% >>"%dataFile%" echo(%%b
endlocal
If you install some tools from a proper Operating System (Unix/Linux) you can do it without any code:
grep -A 999 \[ yourfile
That says look for a [ character in yourfile and print it and up to 999 lines after (-A) it. Unix Utils are available for free here.