I'm trying to get the revision number from a svn update command output. In the file tmpFile.txt I've got the string At revision 58998.
I've run the following command:
findstr /r "\<[0-9][0-9]*\>" "tmpFile.txt"
and I've got
At revision 58998.
Also, running with
findstr /r /o "\<[0-9][0-9]*\>" "tmpFile.txt"
I get
0:At revision 58998.
What's going on and how can I get only the number?
FINDSTR prints out the entire line that matches. It is not able to extract just the matching portion of the line.
You can use FOR /F to parse the output and get just the number.
for /f "tokens=3 delims=. " %%A in (
'findstr /rc:"At revision [0-9][0-9]*\." "tmpFile.txt"'
) do echo %%A
Not a findstr solution, but it works :)
setlocal enabledelayedexpansion
for /f "tokens=3" %%a in (tmpFile.txt) do (
set num=%%a
set num=!num:.=!
)
echo !num!
This will also remove the . from the end.
If your not bothered about the . use
for /f "tokens=3" %%a in (tmpFile.txt) do echo %%a
or for cmd line (no batch)
for /f "tokens=3" %a in (tmpFile.txt) do echo %a
Related
I want to search for the pattern (COM\d+) in the output of mode command. I have tried the:
mode | findstr /R (COM\d+)
But it doesn't return anything. I would appreciate if you could help me know what is the correct way to do this.
P.S.1 Thanks to the comments I now have the mode | findstr /RC:"COM[0-9*]" which yields the line with the given match. Now I need to find a way to print out just the match. maybe using the for /f ... in to loop the string?
P.S.2 I'm being told that mode | findstr /RC:"COM[123456789][0123456789]*" is a safer option.
Here's two simple examples according to my comments:
From the Command Prompt, to satisfy your cmd tag:
(For /F Delims^=: %A In ('Mode^|FindStr "COM[0-9]*:"')Do #For %B In (%A)Do #Set "var=%B")&Call Echo(%var%
From a batch file, to satisfy your batch-file tag:
#(For /F Delims^=: %%A In ('Mode^|FindStr "COM[0-9]*:"')Do #For %%B In (%%A)Do #Set "var=%%B")&Call Echo(%%var%%&Pause
To supplement my comment about WMI, you could alternatively try:
From the Command Prompt:
For /F Skip^=1Delims^= %A In ('WMIC Path Win32_SerialPort Get DeviceID 2^>Nul')Do #For %B In (%A)Do #Echo(%B
From a batch file:
#For /F Skip^=1Delims^= %%A In ('WMIC Path Win32_SerialPort Get DeviceID 2^>Nul')Do #For %%B In (%%A)Do #Echo(%%B&Pause
So, why not just use only one for loop command and addind \ for literal find COM+RegEx in FindStr by this: "\C\O\M[0-9*]."
Obs.: For some reason, the command line do not work for echoing in first run, the COM number for echo/%_com% command, only in second run work, but adding Call to echo/%_com% command, the result showing in first running...
In command line:
for /f "tokens=2delims=COM:" %i in ('mode ^| findstr /RC:"\C\O\M[0-9*]."') do set "_com=%i"&& call echo/%_com%
for /f "tokens=2delims=COM:" %i in ('mode ^| findstr /RC:"\C\O\M[0-9*]."') do set "_com=COM%i"&& call echo/%_com%
for /f "tokens=2delims=COM:" %i in ('mode ^| findstr /RC:"\C\O\M[0-9*]."') do set "_com=COM%i:"&& call echo/%_com%
result 1st line command: 3
result 2nd line command: COM3
result 3rd line command: COM3:
Or in batch file:
#echo off & setlocal enabledelayedexpansion
for /f "tokens=2delims=COM:" %%i in ('mode ^| findstr /RC:"\C\O\M[0-9*]."') do set "_com=%%i"&& echo/!_com!
for /f "tokens=2delims=COM:" %%i in ('mode ^| findstr /RC:"\C\O\M[0-9*]."') do set "_com=COM%%i"&& echo/!_com!
for /f "tokens=2delims=COM:" %%i in ('mode ^| findstr /RC:"\C\O\M[0-9*]."') do set "_com=COM%%i:"&& echo/!_com!
result 1st for command: 3
result 2nd for command: COM3
result 3rd for command: COM3:
See your self by command line:
mode | findstr /RC:"\C\O\M[0-9*]."
result: Status para dispositivo COM3:
So sorry my limited English
It sounds like you just want "COM1" or "COM3" as the output. If so, this'll do it:
for /f "tokens=4 delims=: " %A in ('mode ^| findstr /i /r "COM[0-9]*:"') do #echo %A
It'll produce the following output:
COM1
I found this line of code on this site that echos a text file line by line:
FOR /F %%i IN (filename.txt) DO echo %%i
I am trying to echo a specific line in the text file. How would I accomplish this?
This method get the desired result in a faster way, especially if the file is large.
#echo off
set "line=100"
(for /L %%i in (1,1,%line%) do set /P "result=") < filename.txt
echo %result%
This will echo line 100.
#echo off
set "var=100"
for /f "tokens=1,* delims=:" %%a in ('findstr /n "^" "filename.txt" ^|findstr "^%var%:"') do echo %%b
Lines starting with : will not be complete.
I have a number of text files that are always the same number of lines - 42 and always the same type of information on each line. Also each line starts with a header.
What I would like is a batch script to keep line 30 of the text file remove the others and save the file.
I have tried to look find the line based on the information between two line. In this case the heading on line 30 (Job Notes) and the heading on line 31 (Job Number) and then write the information to a new file.
Line 30 begins with
Job Notes= (information specifically about the job)
Line 31 begins with
Job Number=
This is the code I used (which i found elsewhere on this site) and i am getting no output at all. Have tried other ways as well so don't really have to use this method if you can see a better one, basically i just want line 30 to be the only information in the file.
#ECHO OFF
SETLOCAL
SET "sourcedir=C\Batch"
SET "destdir=C:\Batch\Extract"
for /f "tokens=1 delims=[]" %%a in ('find /n "Job Notes"^<"%sourcedir%\7099.txt" ') do set /a start=%%a
for /f "tokens=1 delims=[]" %%a in ('find /n "Job Number"^<"%sourcedir%\7099.txt" ') do set /a end=%%a
(
for /f "tokens=1* delims=[]" %%a in ('find /n /v ""^<"%sourcedir%\00007099.txt" ') do (
IF %%a geq %start% IF %%a leq %end% ECHO(%%b
)
)>"%destdir%\newfile.txt"
GOTO :EOF
Any help would be greatly appreciated.
David
Option 1, using findstr string numeration
for %%a in (*.log) do (
for /f "tokens=1,* delims=:" %%b in (
'findstr /n "^" "%%a" ^| findstr /b "30:"'
) do (
echo(%%c>"%%a"
)
)
Option 2, using for command skip lines
setlocal disabledelayedexpansion
for %%a in (*.log) do (
set "line="
for /f "usebackq skip=29 delims=" %%b in ("%%a") do if not defined line set "line=%%b"
setlocal enabledelayedexpansion
echo(!line!>"%%a"
endlocal
)
You want you the /N flag with FINDSTR:
FINDSTR /N /R ".*" *.txt | FINDSTR /R "\<30:" > out.txt
Explanation:
FINDSTR /N /R ".*" *.txt
finds every line (".*" with the regex flag /R) in every text file (*.txt) and appends its line number to the front (/N). This is then piped to
FINDSTR /R "\<30:"
which only grabs lines starting with (that's the \< bit) 30:.
#ECHO OFF
SETLOCAL
SET "sourcedir=C\Batch"
SET "destdir=C:\Batch\Extract"
for /f "skip=29tokens=1* delims==" %%a in ('type "%sourcedir%\7099.txt" ') do ECHO(%%b >"%destdir%\newfile.txt"&goto nextstep
:nextstep
GOTO :EOF
should do the job, finding line 30 (by skipping 29) then tokenising on the separating = and having output exactly one, going to the next step in your batch.
Having said that, however - you do realise that you are setting start and end using 7099.txt and then picking the data from 00007099.txt don't you? Does 00007099.txt exist?
And c:\batch seems a mighty strange place to store data files to me. Personally, I'd put batch files there (and include c:\batch into your PATH) but it's your system...
I'm using the following code to get a list of programs being run at start up, and log them to a file.
for /f "skip=2 tokens=1,2*" %%A in ('REG QUERY "HKCU\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run" 2^>NUL') do echo %%A : %%C >> Log.txt
This works with entries where the value name doesn't contain a space, but when it does, such as with "Google Update", it messes up the tokens, and %%C becomes: REG_SZ <path>, instead of just the path.
Does anyone have a better way to query the registry and log its values?
Well I got one working solution, I'd still love to see if anyone has anything better.
for /f "skip=2 tokens=*" %%A in ('REG QUERY "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" 2^>NUL') do (
set regstr=%%A
set regstr=!regstr: =^|!
for /f "tokens=1,3 delims= |" %%X in ("!regstr!") do (
echo %%X : %%Y
)
)
Version specific, works in XP, does not work in Win 7 - see comments for details.
Columns in the output are separated by tab char (0x09), so use only tab as a separator:
for /f "skip=2 tokens=1,2* delims= " %%A
This does not show well because of how markup handles white chars, but the character after delims= must be actual TAB
Here's a better way via WMI calling the Win32_StartupCommand class, results output to screen as well as a CSV file in the same folder as per script name:
#echo off
setlocal enabledelayedexpansion
cd \ & pushd "%~dp0"
if exist "%~n0.tmp" (del /f /q "%~n0.tmp")
if exist "%~n0.csv" (del /f /q "%~n0.csv")
wmic /namespace:\\root\cimv2 path Win32_StartupCommand get /all /format:csv >"%~n0.tmp"
for /f "tokens=1,2,3,4,5,6,7,8,9 usebackq delims=, skip=2" %%a in (`type "%~n0.tmp"`) do (
echo %%b, %%c >>"%~n0.csv"
echo %%b, %%c
)
if exist "%~n0.tmp" (del /f /q "%~n0.tmp")
popd & endlocal
exit /b 0`
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: