I want create a batch file to find the total number of commas in the first line of text file.
Sample Text File
input.txt
12345,Bhavik
12323,Bhavik,Sanghvi
Output
1
I tried to surf net for this but couldnt find a solution, please help
Here's another simple solution to this question.
#echo off
setlocal enabledelayedexpansion
set LF=^
::Above 2 blank lines are critical - do not remove
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
set /p var=<input.txt
echo "%var:,="!cr!!lf!"..***..%">temp.file
find /c "..***.." <temp.file
del temp.file
#echo off
setlocal EnableDelayedExpansion
rem Read the first line
set /P "line=" < input.txt
rem Store it in a text file
> before.txt echo !line!
rem Store the line without commas in a second file
> after.txt echo !line:,=!
rem Get the difference in sizes between both files
set "diff="
for %%a in (before.txt after.txt) do (
if not defined diff (
set "diff=%%~Za"
) else (
set /A "diff-=%%~Za"
)
)
del before.txt after.txt
echo %diff%
If, rather than being hampered by the awful Windows BATCH tools, you install awk from the Unix tools for Windows here, you can do this:
awk -F, 'NR==1{print NF-1;exit}' input.txt
That says... "Run awk and use commas as the separator to divide fields. On line 1, print the number of fields on this line minus 1, then exit. Do that for file input.txt."
gawk is just a slightly different version of awk if you get that one in the Unix Utils package. You may need to replace the single quotes with double ones to accommodate Windows' lack of abilities.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q35826440.txt"
:: first method
SET /a count=0
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO SET "line=%%a"&GOTO got1
:got1
SET "line=%line:"=%"
IF NOT DEFINED line ECHO method 1: %count% found&GOTO method2
IF "%line:~-1%"=="," SET /a count+=1
SET "line=%line:~0,-1%"
GOTO got1
:: second method
:method2
SET /a count=-1
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO SET "line=%%a"&GOTO got2
:got2
SET "line=%line:"=%"
SET "line=%line:;=%"
SET "line=%line: =%"
SET "line=%line:,=x,x%"
FOR %%a IN (%line%) DO SET /a count+=1
ECHO method 2: %count% found
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
I used a file named q35826440.txt containing your data for my testing.
Two methods - both read the first line to line, then removes any " characters.
The first then mechanically loops, checking whether the last character is a comma, counting if it is and removing the last character until the string found is empty.
The second replaces all ; and Space characters (for good measure, Tab could be removed too) and then replacing commas with x,x.
The result is that the only separators left are commas, and there will be 1 more item in the list so formed than there are commas.
Hence, start the counter at -1 and increment for each element found in the list.
Next solution (similar to Magoo's second method) seems to treat even ˙cmd˙ and .bat poisonous characters supposed in input file:
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "infile=D:\bat\SO\files\35826440input.txt" change to suit your circumstances
set /A "commacount=-1"
for /F "usebackq delims=" %%G in ("%infile%") do (
set "line=%%G"
call :parseline
if /I not "%~1"=="/all" goto :continue
)
:continue
echo script continues here
ENDLOCAL
exit /B
:parseline
rem treat unbalanced doublequote in next line
set "lineToParse=%line:"=§%"
set "lineToParse=%lineToParse:,=","%"
set /A "commacount=-1"
for %%g in ("%lineToParse%") do (
set /A "commacount+=1"
rem echo %line%, !commacount!, %%g
)
echo %commacount% "%line%"
goto :eof
Output (with input file listing):
==> D:\bat\SO\35826440.bat
1 "12345,Bhavik"
script continues here
==> D:\bat\SO\35826440.bat /all
1 "12345,Bhavik"
2 "12323,Bhavik,Sanghvi"
3 "12323,Bhavik,Sanghvi,three"
0 "zero"
1 ",1 leading"
2 ",,2 leading"
1 "trailing,"
2 "2 trailing,,"
2 "2 middle,,mid"
4 "!OS!,!,!!,!!!,exclamations"
4 "%OS%,%,%%%,%%,percents"
8 "&,|,>,<,",",;,=,miscelaneous"
0 "unbalanced"doublequote"
script continues here
==> type D:\bat\SO\files\35826440input.txt
12345,Bhavik
12323,Bhavik,Sanghvi
12323,Bhavik,Sanghvi,three
zero
,1 leading
,,2 leading
trailing,
2 trailing,,
2 middle,,mid
!OS!,!,!!,!!!,exclamations
%OS%,%,%%%,%%,percents
&,|,>,<,",",;,=,miscelaneous
unbalanced"doublequote
==>
Using the cmd prompt, I am trying to use the findstr feature to output certain criteria from a txt file.
My txt file contains a list of .exe names, including comments. There are alot of them- I want to parse out only the "name.exe" of each line.
Here are examples of different lines in the txt file
C:\\Programme\\Windows Media Player\\mplayer2.exe""=dword:00000000
HOPSTER.EXE; Hopster
Out of these, I want only "mplayer2.exe" and "hopster.exe" to be included in the print out.
Instead, I receive this:
script: findstr "*.exe" Exies.txt
output:
.\Exies.txt:""C:\\Programme\\Windows Media Player\\mplayer2.exe""=dword:00000000
.\Exies.txt:HOPSTER.EXE; Hopster
I was able to pull out some items using this script, findstr /e ".exe" Exies.txt,
but am having trouble with the other examples above.
Any help? Please and thank you.
I don't think you can do it only with findstr (I'm not aware of any FINDSTR output format that would let you print only the matched patterns).
Instead, you could use select-string from PowerShell:
C:\>powershell
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.
PS C:\> select-string -Path Exies.txt -Pattern "([a-z0-9]+)\.exe" -AllMatches | % { $_.Matches } | % { $_.Value }
mplayer2.exe
HOPSTER.EXE
PS C:\>
Here is a pure batch solution (there are many explanatory rem-arks in the code, so don't be shocked about the extent).
The most tricky parts are to get the offset position beyond the ".exe" extension for proper truncation of the string read from each line of Exies.txt, and to determine the start position of the file name:
#echo off
setlocal EnableDelayedExpansion
rem regular expression for `findstr` which means:
rem a string consisting of a sub-string with at least one character,
rem NOT containing any of '\?*/:<>"', followed by ".exe";
rem such strings are considered as valid executable file names
set REGEX="[^\\?\*/:<>|\""]*[^\\?\*/:<>|\""]\.exe"
rem parse the output of `findstr` with a `for /F` loop
rem (note that `findstr` is told to do case-insensitive searches)
for /F "tokens=*" %%F in ('findstr /I /R %REGEX% Exies.txt 2^> nul') do (
rem assign a single matching line to variable `LINE`
set "LINE=%%F"
rem call sub-routine to retrieve length of string portion after the
rem (first) occurrence of ".exe"; the length is also equal to the
rem character offset of the string portion after the ".exe" occurrence
call :STRLEN "!LINE:*.exe=!" LEN > nul
rem use another `for` loop to truncate `LINE` after ".exe";
rem so afterwards we have everything up to the ".exe" portion
for %%A in (!LEN!) do (
set "LINE=!LINE:~,-%%A!"
) & rem next %%A
rem replace double-quotes '"' and colons ':' by backslashes '\'
set "LINE=!LINE:"=\!
set "LINE=!LINE::=\!"
rem wrap around another `for` loop to extract the file name portion
rem (this is done to remove any paths from the "*.exe" file name)
for %%B in ("!LINE!") do (
set "LINE=%%~nxB"
) & rem next %%B
rem safety check if extracted "*.exe" file name still matches the
rem regular expression (necessary if ".exe" occurs twice in a line)
echo !LINE! | findstr /I /R %REGEX% > nul 2>&1
if not ErrorLevel 1 (
rem output final "*.exe" file name
echo !LINE!
) & rem end if
) & rem next %%F
endlocal
exit /B
:STRLEN
rem this constitutes a sub-routine to get the length of a string
setlocal EnableDelayedExpansion
set "STR=%~1"
if "%STR%" EQU "" (
set /A LEN=0
) else (
set /A LEN=1
for %%I in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if not "!STR:~%%I!" EQU "" (
set /A LEN+=%%I
set "STR=!STR:~%%I!"
) & rem end if
) & rem next %%I
) & rem end if
endlocal & set /A LEN=%LEN%
if not "%~2" EQU "" set %~2=%LEN%
echo %LEN%
exit /B
Assumptions:
the ".exe" portion occurs once per line of Exies.txt only;
the file name consists of at least one character other than these \?*/:<>|";
the file name is delimited to the left by
either a backslash \ or a colon : (meaning that a path has been specified),
or a double-quote " (it might have been enclosed in a pair of such);
I am totally new on writing batch script,busy with the tutorials with the example below I can learn a thing or two.I really need help to write a batch script to insert a line of text at the middle of existing text file.
For example given the file myfile.txt with the contents:
a
bcd
efg
hjiklmnop
q
rs
t
uvwxyz
The the command ./put-in-middle.sh "=== === ===" myfile.txt
should modify the file to:
a
bcd
efg
hjiklmnop
=== === ===
q
rs
t
uvwxyz
#echo off
rem Count the number of lines in the file with FIND
for /F %%a in ('find /C /V "" ^< %2') do set numLines=%%a
rem Get the number of middle line
set /A middle=numLines/2
rem Process all lines, use FINDSTR /N to insert line numbers
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" %2') do (
rem Echo the original line
echo/%%b
rem If the line is the middle one...
if %%a equ %middle% (
rem Insert the new line
echo %~1
)
)
Create previous Batch file as put-in-middle.bat and execute it this way:
put-in-middle "=== === ===" myfile.txt
Notes:
Previous program does not check for errors, like missing parameters. This checking may be added, if you wish.
The slash in the command echo/%%b is inserted to avoid the message "ECHO is on" if the line is empty. If the line may contain the string "/?", then the command should be changed to echo(%%b to avoid that the echo help be displayed in this case (the left parentheses is the only character that do that).
If the file contains Batch special characters, like < > | & ), the echo/%%b command fail. In this case, a special processing of files lines must be added. The same point apply to the new inserted line.
Previous program just display in the screen the new file. If you want to replace the original file, the output must be redirected to an auxiliary file and replace the original one at end:
.
(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" %2') do (
. . .
)) > auxiliar.txt
move /Y auxiliar.txt %2
Using sed and assuming even number of lines:
sed $(( $(wc input -l | cut -d' ' -f1) / 2))'a=== === ===' input
And this is the script version put-in-middle.sh:
line=$1
file=$2
sed $(( $(wc $file -l | cut -d' ' -f1) / 2))"a$line" $file
I have a text file which has more than 200 lines in it, and I just want to add a new line before line 4. I'm using Windows XP.
Example text file before input:
header 1
header 2
header 3
details 1
details 2
After output:
header 1
header 2
header 3
<----- This is new line ---->
details 1
details 2
I believe you are using the
echo Text >> Example.txt
function?
If so the answer would be simply adding a "." (Dot) directly after the echo with nothing else there.
Example:
echo Blah
echo Blah 2
echo. #New line is added
echo Next Blah
DISCLAIMER: The below solution does not preserve trailing tabs.
If you know the exact number of lines in the text file, try the following method:
#ECHO OFF
SET origfile=original file
SET tempfile=temporary file
SET insertbefore=4
SET totallines=200
<%origfile% (FOR /L %%i IN (1,1,%totallines%) DO (
SETLOCAL EnableDelayedExpansion
SET /P L=
IF %%i==%insertbefore% ECHO(
ECHO(!L!
ENDLOCAL
)
) >%tempfile%
COPY /Y %tempfile% %origfile% >NUL
DEL %tempfile%
The loop reads lines from the original file one by one and outputs them. The output is redirected to a temporary file. When a certain line is reached, an empty line is output before it.
After finishing, the original file is deleted and the temporary one gets assigned the original name.
UPDATE
If the number of lines is unknown beforehand, you can use the following method to obtain it:
FOR /F %%C IN ('FIND /C /V "" ^<%origfile%') DO SET totallines=%%C
(This line simply replaces the SET totallines=200 line in the above script.)
The method has one tiny flaw: if the file ends with an empty line, the result will be the actual number of lines minus one. If you need a workaround (or just want to play safe), you can use the method described in this answer.
You can use:
type text1.txt >> combine.txt
echo >> combine.txt
type text2.txt >> combine.txt
or something like this:
echo blah >> combine.txt
echo blah2 >> combine.txt
echo >> combine.txt
echo other >> combine.txt
Suppose you want to insert a particular line of text (not an empty line):
#echo off
FOR /F %%C IN ('FIND /C /V "" ^<%origfile%') DO SET totallines=%%C
set /a totallines+=1
#echo off
<%origfile% (FOR /L %%i IN (1,1,%totallines%) DO (
SETLOCAL EnableDelayedExpansion
SET /p L=
IF %%i==%insertat% ECHO(!TL!
ECHO(!L!
ENDLOCAL
)
) >%tempfile%
COPY /Y %tempfile% %origfile% >NUL
DEL %tempfile%
This is my input file content which I am using to copy to the output file.
#sdfs|dfasf|sdfs|
sdfs|df!#$%%*&!sdffs|
sasdfasfa|dfsdf|#sdfs|
What I need to do is to omit the first character '#' and last character '|' in the output file.
So the output will be,
sdfs|dfasf|sdfs|
sdfs|df!#$%%*&!sdffs|
sasdfasfa|dfsdf|#sdfs
Batch script is new to me, but I tried my best and tried these codes,
:: drop first and last char
#echo off > xyz.txt & setLocal EnableDelayedExpansion
for /f "tokens=* delims=" %%a in (E:\abc1.txt) do (
set str=%%a
set str=!str:~1!
echo !str!>> xyz.txt
)
As you can see it is not able to produce the required output.
The output now being produced is like
sdfs|dfasf|sdfs|
dfs|dfsdffs|
asdfasfa|dfsdf|#sdfs|
I don't know why the string !#$%%*&! is also getting ripped !?
Next script, call file far.vbs, anf create your new file.
Code:
set OldFile=E:\abc1.txt
set NewFile=E:\xyz.txt
echo. > "%NewFile%"
start far.vbs "%NewFile%" "%OldFile%"
far.vbs — delete first and last char from file.
Create new file far.vbs in the same folder as first script, and paste the following code:
Set OldFile = CreateObject("Scripting.FileSystemObject")
Set rdOldFile = OldFile.OpenTextFile(Wscript.Arguments(1), 1)
oContent = rdOldFile.ReadAll
rdOldFile.Close
Set lOldFile = CreateObject("Scripting.FileSystemObject")
Set lrdOldFile = OldFile.OpenTextFile(Wscript.Arguments(1), 1)
oLen = len(lrdOldFile.ReadAll)
lrdOldFile.Close
oData = oContent
oData = Right(oContent, oLen-1)
oData = Left(oData, oLen-2)
Set NewFile = CreateObject("Scripting.FileSystemObject")
Set fData = NewFile.OpenTextFile(Wscript.Arguments(0), 2)
fData.WriteLine (oData)
fData.Close
batch is never a strong point for file processing and text manipulation. If you have the luxury, you can download sed from GNU win32, then use this one liner.
C:\test>sed "/#/{s/^#//;s/|$//}" file
sdfs|dfasf|sdfs
sdfs|df!#$%%*&!sdffs|
sasdfasfa|dfsdf|#sdfs
I can't debug my code right now, but try:
:: drop first and last char
#echo off > xyz.txt
#echo off > xyz2.txt
#echo off > xyz3.txt
setLocal EnableDelayedExpansion
for /f "tokens=* delims= " %%a in (E:\abc1.txt) do (
set /a N+=1
echo %%a >> xyz.txt
echo %%b >> xyz2.txt
echo %%%c >> xyz3.txt