I'm struggling.. I have a text file that contains lots of mac addresses - what I want to do is find any duplicate mac addresses that appear.
Any help would be greatly appreciated.. Kind Regards Craig.
Assuming a line looks like this:
000000000944 000000000944 0 <client-mac>00:11:50:A0:BE:26</client-mac>
this should do:
#echo off
copy nul out.txt >nul
for /f "tokens=3 delims=<>" %%i in (file.txt) do (
find "%%i" out.txt>nul && (
echo doublette: %%i>>out.txt
) || (
echo unique: %%i>>out.txt
)
)
&& means: "if errorlevel = 0 then do..."
|| means: "if errorlevel is not 0 then do..."
#echo off
setlocal EnableDelayedExpansion
(for /F "tokens=3 delims=<>" %%a in (input.txt) do (
if defined macAddress[%%a] (
echo Duplicated mac address: %%a
) else (
set macAddress[%%a]=true
)
)) > output.txt
This can be accomplished in PowerShell without too much difficulty:
get-content "test.dat" | select-string '((?:[0-9A-F]{2}:){5}[0-9A-F]{2})' | foreach-object {
$_.Matches[0].Groups[1].Value
} | sort-object -unique | out-file "results.txt"
Related
I have a textfile/logfile called textexample.txt with a lot of lines which was generated from a 3rd Party Software and therefore does contain a lot of special characters.
Now im searching for some special keywords in this logfile and therefore i use findstr.
The problem is that i want to store every character which has to be escaped in a variable called charsToEscape, but this is not working proper. Is there any 'simple' solution for my example?
Here is the textfile "textexample.txt" im searching in:
17:09:47| | |OS ver : 1.2 AB:0.0 CD:1234 KType:-1
17:09:48| |InitInstance() |Start copy files from Section=Files
17:09:49| | | ******************************
17:09:50| |StartExe |Here is the Value (1234) i am searching"
17:09:50| |StartExe |your path="C:\Some\Specific\Path"
17:09:50| |someRandomWords |WaitLevel="1" (default value)
Here is my Batchfile:
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
:MAIN
setlocal
::REM List with the expected Values im searching for..
set "expected_value_pool=9876 turn 1234 failure adios"
call :SearchValue "%expected_value_pool%" "readback_value"
if "!errorlevel!" equ "0" (
echo readback=!readback_value!
)
pause
exit /b 0
REM Function, which checks if the give return value is in a specific textfile (line for line check)
:SearchValue
setlocal
set "_expected_value_pool=%~1"
set "_readback_value=%~2"
set "file=textexample.txt"
set "charsToEscape=/ \ > < ? | " - $ ( ) [ ] { } : = ."
set "escapeChar=^"
for /f "tokens=*" %%a in (%file%) do (
set "act_line=%%a"
for %%c in (%charsToEscape%) do (
set "act_line=!act_line:%%c=%escapeChar%%%c!"
)
for %%i in (%_expected_value_pool%) do (
echo !act_line!|findstr /r "^.*%%i.*$" >NUL
if "!errorlevel!" equ "0" (
(endlocal
if "%_readback_value%" neq "" (set "%_readback_value%=%%i")
)
exit /b 0
)
)
)
exit /b 1
UPDATE:
i get the error ">" cant be processed syntactically at this point from the line set "charsToEscape=/ \ > < ? | " - $ ( ) [ ] { } : = ." due to the special characters which cannot be proper processed
I have multiple text files contains integer on each row. Can loop for /f calculate (add) from each row of each file sequentially?
Lets say the text files are like this:
File1.txt
123
213
321
File2.txt
111
222
333
File3.txt
333
222
111
Is it possible iterate over multiple files content and sum the like rows IE:
file1 row1 + file2 row1 + file3 row1
file1 row2 + file2 row2 + file3 row2
file1 row3 + file2 row3 + file3 row3
:: operation for 1st row of each file should be:
Set /A calc=123+111+333
echo !calc!
After googling around, I could not find any solution similar to my problem.
Appreciate if anyone can provide insight on this.
Thanks
you can use a single for loop over the output of findstr to build counts from each lines value.
#Echo off & CD /D "%~dp0"
cls
Setlocal
For /f "tokens=1 Delims==" %%g in ('set Line[ 2^> nul')Do Set "%%g=" 2> nul
For /f "tokens=2,3 delims=:" %%i in ('%Systemroot%\System32\Findstr.exe /n /r "^[0123456789]*$" "file*.txt"')Do (
Set /A "Line[%%i]+=%%j+0" 2> nul
)
Set Line[
Endlocal
You can use an array this way:
#echo off
setlocal EnableDelayedExpansion
for %%f in (file*.txt) do (
set "i=1"
for /F %%n in (%%f) do set /A "calc[!i!]+=%%n, i+=1"
)
set /A i-=1
for /L %%i in (1,1,%i%) do echo calc[%%i] = !calc[%%i]!
This batch-file that is run by cmd uses a PowerShell script. It creates a hash item for each line and accumulates the sum for each.
#powershell.exe -NoLogo -NoProfile -Command ^
"$h = #{};" ^
"Get-ChildItem -Filter 'filefile*.txt' |" ^
"ForEach-Object {" ^
"$LineNumber = 0;" ^
"Get-Content -Path $_.FullName |" ^
"ForEach-Object { $h[$LineNumber++] += [int]$_ }" ^
"};" ^
"0..($h.Count-1) | ForEach-Object { $h[$_] }"
This is a lot easier and clearer if written in a .ps1 file.
$h = #{}
Get-ChildItem -Filter 'filefile*.txt' |
ForEach-Object {
$LineNumber = 0
Get-Content -Path $_.FullName |
ForEach-Object { $h[$LineNumber++] += [int]$_ }
}
0..($h.Count-1) | ForEach-Object { $h[$_] }
You may see this get downvoted by someone who thinks PowerShell is not part of cmd. PowerShell is just as much a part of cmd as are find.exe, ipconfig.exe, and setx.exe. PowerShell is available on all supported Windows systems.
You can use findstr in a single for loop and set results sequentially per file:
#echo off & setlocal enabledelayedexpansion
for /f "tokens=1*delims=:" %%i in ('findstr /R "[0-9]" file*.txt') do (
set /a %%~ni+=1 & set /a _Result[!%%~ni!]+=%%j
)
set _Result
Each line per file's lines will be added together, result (based of your current examples:
For a drop single sum files on me approach:-
Summation.bat
#echo off & SETLOCAL ENABLEDELAYEDEXPANSION & Title Summation
for /f "tokens=1* delims=[]" %%A in ('find /n /v "%Title%" "%~1"') do (set "L%%A=%%B" & set "count=%%A")
set calc=0 & for /L %%i in (1,1,!count!) do (set /a calc = !calc! + !L%%i!)
echo/ & echo Line Count = !count! ^& Sum = !calc! & echo/ & pause
Command Line Usage >Summation File1.txt
NOTE as per comment by #T3RROR below
I misread your question as "Provide summation for a file at a time."
HOWEVER have kept it here for others wishing to sum each file.
Good batching, and may the cmd be with you :-)
I have multiple string that come from a reg query inside a for loop.
I want to validate for each of them if it has certain words and do actions if it has.
My code is this:
for /l %%g in (0 1 3) do (
echo HOME%%g
for /f "tokens=1,2,3*" %%h in ('reg query \\%%c\HKLM\SOFTWARE\ORACLE\HOME%%g /v ORACLE_HOME') do (
echo HOME%%g
echo %%j
echo %%j | findstr /I /R /C:"806"
if %ERRORLEVEL% equ 0 (
echo YES
) else (
echo NO
)
echo %%j | findstr /C:".isuites."
if %ERRORLEVEL% equ 0 (
echo YES
) else (
echo NO
)
echo %%j | findstr /I ora90
if errorlevel 0 (
echo YES
) else (
echo NO
)
echo %%j | findstr /I forms10
if errorlevel 0 (
echo YES
) else (
echo NO
)
)
)
The problem is that is does not validates the string as seen in the output
HOME0
HOME0
ECHO is off.
YES
YES
YES
YES
HOME0
d:\oracle\806
d:\oracle\806
YES
YES
YES
YES
HOME1
HOME1
ECHO is off.
YES
YES
YES
YES
HOME1
d:\oracle\iSuites
YES
YES
YES
YES
HOME2
HOME2
ECHO is off.
YES
YES
YES
YES
HOME2
d:\oracle\ora90
YES
YES
d:\oracle\ora90
YES
YES
HOME3
HOME3
ECHO is off.
YES
YES
YES
YES
HOME3
D:\oracle\forms10g
YES
YES
YES
D:\oracle\forms10g
YES
Some corrections are needed in your code
Change for %%h into
for /f "tokens=1,2,*" %%h in ('reg query \\%%c\HKLM\SOFTWARE\ORACLE\HOME%%g /v ORACLE_HOME ^| find "REG_SZ" ') do (
That way, the ORACLE_HOME key name will be in %%h, the REG_SZ type in %%i and the folder in %%j (i supose this is what you intended)
With this done, the next problem is errorlevel checks
When a block of code (code inside parenthesis) is parsed, all variable reads are replaced with the value inside the variable before starting to execute the block. So, if you use %errorlevel% inside you block of code, as this variable read has been replaced with the value of the variable before starting to execute, you will not see the real value.
You can use delayed expansion (include setlocal enabledelayedexpansion at the start of batch file) and change the syntax from %errorlevel% to !errorlevel! to indicate to the parser that the variable read should be delayed until the moment the command is executed.
Or you can use the if errorlevel n ... syntax. In this case you should remember that the condition will be true for any errorlevel value greater or equal than the indicated value.
That is, if errorlevel is 1, both if errorlevel 1 and if errorlevel 0 will be true. For this reason, the proper way of checking error level is to check from greater values to lower values
echo %%j | findstr .....
if errorlevel 1 (
...
) else (
...
)
So, your code should be something like
....
....
for /l %%g in (0 1 3) do (
echo Testing HOME%%g
echo ---------------------------------
for /f "tokens=1,2,*" %%h in (
'reg query \\%%c\HKLM\SOFTWARE\ORACLE\HOME%%g /v ORACLE_HOME 2^>nul ^| find "REG_SZ" '
) do (
echo %%j | findstr /L /C:"806"
if errorlevel 1 (
echo NO
) else (
echo YES
)
echo %%j | findstr /C:".isuites."
if errorlevel 1 (
echo NO
) else (
echo YES
)
echo %%j | findstr /I /C:"ora90"
if errorlevel 1 (
echo NO
) else (
echo YES
)
echo %%j | findstr /I /C:"forms10"
if errorlevel 1 (
echo NO
) else (
echo YES
)
)
)
)
edited to adapt to comments
Some of the HOMEn will not be echoed if they does not exist in registry. To "solve" it, the error output from req query is included in the data to be parsed and it is tested if the string ERROR: is found.
for /l %%g in (0 1 3) do (
echo Testing HOME%%g
echo ---------------------------------
for /f "tokens=1,2,*" %%h in (
'reg query \\%%c\HKLM\SOFTWARE\ORACLE\HOME%%g /v ORACLE_HOME 2^>^&1 ^| findstr /L /C:"REG_SZ" /C:"REG_EXPAND_SZ" /C:"ERROR:" '
) do (
for %%z in ("806" ".isuites." "ora90" "forms10") do (
(if "%%h"=="ERROR:" (echo() else (echo %%j)) | findstr /i /c:"%%~z"
if errorlevel 1 (
echo NO
) else (
echo YES
)
)
)
)
)
I have Batch code like this
#echo off
:begin
SET d=netstat -an | find /c "0.0.0.0:80"
rem echo %d%
if %%d == "2" (
echo true
pause
rem exit
) else (
echo false
pause
rem GOTO begin
)
I want make netstat stetment output stored in variable d, and d became parameter from If cluse, What wrong with my file ?
You don't need to set a variable in your case.
This should work :
netstat -an | find /c "0.0.0.0:80" && echo true || echo False
But if you need to have this value in a variable you can do like this :
#echo off
for /f %%a in ('netstat -an ^| find /c "0.0.0.0:80"') do set D=%%a
if %D% equ 2 (
echo true
) else (
echo false)
file 1
A
B
C
file 2
B
C
D
file1 + file2 =
A
B
C
D
Is it possible to do using cmd.exe?
If you can affort to use a case insensitive comparison, and if you know that none of the lines are longer than 511 bytes (127 for XP), then you can use the following:
#echo off
copy file1.txt merge.txt >nul
findstr /lvxig:file1.txt file2.txt >>merge.txt
type merge.txt
For an explanation of the restrictions, see What are the undocumented features and limitations of the Windows FINDSTR command?.
Using PowerShell:
Get-Content file?.txt | Sort-Object | Get-Unique > result.txt
For cmd.exe:
#echo off
type nul > temp.txt
type nul > result.txt,
copy file1.txt+file2.txt temp.txt
for /f "delims=" %%I in (temp.txt) do findstr /X /C:"%%I" result.txt >NUL ||(echo;%%I)>>result.txt
del temp.txt
First part (merging two text files) is possible. (See Documentation of copy command)
copy file1.txt+file2.txt file1and2.txt
For part 2, you can use sort and uniq utilities from CoreUtils for Windows. This are windows port of the linux utilities.
sort file1and2.txt filesorted.txt
uniq filesorted.txt fileunique.txt
This has a limitation that you will lose track of original sequencing.
Update 1
Windows also ships with a native SORT.EXE.
Update 2
Here is a very simple UNIQ in CMD script
You may also use the same approach of Unix or PowerShell with pure Batch, developing a simple uniq.bat filter program:
#echo off
setlocal EnableDelayedExpansion
set "prevLine="
for /F "delims=" %%a in ('findstr "^"') do (
if "%%a" neq "!prevLine!" (
echo %%a
set "prevLine=%%a"
)
)
EDIT: The program below is a Batch-JScript hybrid version of uniq program, more reliable and faster; copy this program in a file called uniq.bat:
#if (#CodeSection == #Batch) #then
#CScript //nologo //E:JScript "%~F0" & goto :EOF
#end
var line, prevLine = "";
while ( ! WScript.Stdin.AtEndOfStream ) {
line = WScript.Stdin.ReadLine();
if ( line != prevLine ) {
WScript.Stdout.WriteLine(line);
prevLine = line;
}
}
This way, you may use this solution:
(type file1.txt & type file2.txt) | sort | uniq > result.txt
However, in this case the result lost the original order.
The solution below assume that both input files are sorted in ascending order using the same order of IF command's comparison operators and that does not contain empty lines.
#echo off
setlocal EnableDelayedExpansion
set "lastLine=ΓΏ"
for /L %%i in (1,1,10) do set "lastLine=!lastLine!!lastLine!"
< file1.txt (
for /F "delims=" %%a in (file2.txt) do (
set "line2=%%a"
if not defined line1 set /P line1=
if "!line1!" lss "!line2!" call :advanceLine1
if "!line1!" equ "!line2!" (
echo !line1!
set "line1="
) else (
echo !line2!
)
)
)
if "!line1!" neq "%lastLine%" echo !line1!
goto :EOF
:advanceLine1
echo !line1!
set "line1="
set /P line1=
if not defined line1 set "line1=%lastLine%"
if "!line1!" lss "!line2!" goto advanceLine1
exit /B
this joins, sorts and reduce excessive size after PowerShell
Get-Content file?.txt | Sort-Object | Get-Unique | Set-Content -Encoding UTF8 result.txt