I have a large file full of lines like this...
19:54:05 10.10.8.5 [SERVER] Response sent: www.example.com. type A by 192.168.4.5
19:55:10 10.10.8.5 [SERVER] Response sent: ns1.example.com. type A by 192.168.4.5
19:55:23 10.10.8.5 [SERVER] Response sent: ns1.example.com. type A by 192.168.4.5
I don't care about any of the other data, only what's after the "response sent:"
I'd like a sorted list of the most common occurrences of the domain-names.
Problem is I won't know all the domain-names in advance, so I can't just do a search for the string.
Using the example above I'd like the output to be along the lines of
ns1.example.com (2)
www.example.com (1)
...where the number in ( ) is the counts of that occurrence.
How/what could I use to do this on Windows? The input file is .txt - the output file can be anything. Ideally a command-line process, but I'm really lost so I'd be happy with anything.
Cat is kinda out of the bag so lets try and help a little. This is a PowerShell solution. If you are having issues with how this works I encourage you to research the individual parts.
If you text file was "D:\temp\test.txt" then you could do something like this.
$results = Select-String -Path D:\temp\test.txt -Pattern "(?<=sent: ).+(?= type)" | Select -Expand Matches | Select -Expand Value
$results | Group-Object | Select-Object Name,Count | Sort-Object Count -Descending
Using your input you would get this for output
Name Count
---- -----
ns1.example.com. 2
www.example.com. 1
Since there is regex I have saved a link that explains how it works.
Please keep in mind that SO is, of course, a site that helps programmers and programming enthusiasts. We are devoting our free time where as some people get paid to do this.
Can you do it in PHP?
<?php
$lines = file($filename, FILE_IGNORE_NEW_LINES);
foreach($lines as $value) {
$arr = explode(' ', $value);
$domainarr[] = $arr[5];
}
$occurence = array_count_values($domainarr);
print_r($occurence);
?>
This is in batch:
#echo off
setlocal enabledelayedexpansion
if exist temp.txt del temp.txt
for /f "tokens=6" %%a in (input.txt) do (Echo %%a >> temp.txt)
for /f %%a in (temp.txt) do (
set /a count=0
set v=%%a
if "!%%a!" EQU "" (
for /f %%b in ('findstr /L "%%a" "temp.txt"') do set /a count+=1
set %%a=count
Echo !v:~0,-1! ^(!count!^)
)
)
del temp.txt
Currently it prints it out to the screen. If you would like to redirect it to a text file replace:
Echo !v:~0,-1! ^(!count!^)
with:
Echo !v:~0,-1! ^(!count!^) >> output.txt
This outputted:
www.example.com (1)
ns1.example.com (2)
With the sample data
This Batch file solution should run faster:
#echo off
setlocal
rem Accumulate each occurance in its corresponding array element
for /F "tokens=6" %%a in (input.txt) do set /A "count[%%a]+=1"
rem Show the result
for /F "tokens=2,3 delims=[]=" %%a in ('set count[') do echo %%a (%%b)
Output:
ns1.example.com. (2)
www.example.com. (1)
To store the result in a file, change the last line by this one:
(for /F "tokens=2,3 delims=[]=" %%a in ('set count[') do echo %%a (%%b^)) > output.txt
Related
Here is my text file:
==================================================
Folder : D:\T\New folder
==================================================
==================================================
Folder : D:\T\Z-Ai
==================================================
==================================================
Folder : D:\T\Z-BiN
==================================================
I need to extract the paths from this file, so I have something like this:
D:\T\New folder
D:\T\Z-Ai
D:\T\Z-BiN
It seems I should use findstr TargetWord TargetFile.txt command. and Also it seems I can use regex like this: findstr /r "^[a-z][a-z]$ ^[a-z][a-z][a-z]$"
But I do not know how to loop through found targets or get the list of output. any help is really appreciated.
Based on your comment, you want to use the result to perform an xcopy task, it seems you really want something like this. Note I used example.txt as input file, and DESTINATION where you should add your destination, including the relevant xcopy switches you require:
#echo off
for /f "tokens=2*" %%i in ('type example.txt ^| findstr /i ":\\"') do xcopy "%%~j\*" DESTINATION
Alternatively we can use the findstr directly on Folder
#echo off
for /f "tokens=2*" %%i in ('type example.txt ^| findstr /i "Folder"') do xcopy "%%~j\*" DESTINATION
You can do like this :
#echo off
Title Extract list of path in a file using batch script
set "TxtList=MyList.txt"
Set "OutPutData=Output.txt"
Call :Extract "%TxtList%" "%OutPutData%"
Start "" "%OutPutData%"
Exit
::*****************************************************
:Extract <InputData> <OutPutData>
(
echo Data = WScript.StdIn.ReadAll
echo Data = Extract(Data,"[\w]:(\\[0-9\sA-Za-z\-]*)+"^)
echo WScript.StdOut.WriteLine Data
echo '************************************************
echo Function Extract(Data,Pattern^)
echo Dim oRE,oMatches,Match,Line
echo set oRE = New RegExp
echo oRE.IgnoreCase = True
echo oRE.Global = True
echo oRE.Pattern = Pattern
echo set oMatches = oRE.Execute(Data^)
echo If not isEmpty(oMatches^) then
echo For Each Match in oMatches
echo Line = Line ^& Trim(Match.Value^) ^& vbcrlf
echo Next
echo Extract = Line
echo End if
echo End Function
echo '************************************************
)>"%tmp%\%~n0.vbs"
cscript /nologo "%tmp%\%~n0.vbs" < "%~1" > "%~2"
If Exist "%tmp%\%~n0.vbs" Del "%tmp%\%~n0.vbs"
exit /b
::****************************************************
For Windows. you can use powershell.
select-string -Path c:\tmp\file.txt -Pattern '[A-Z]:(\\[0-9\ A-Za-z\-]*)+' -AllMatches | % { $_.Matches } | % { $_.Value }
In my opinion, For /F is all you need for the task. Although using Type may be useful in some situations, there's no need to use find.exe or findstr.exe for this task as you don't need to match a particular glob/pattern:
#For /F "EOL==Tokens=2*UseBackQ" %%A In ("TargetFile.txt")Do #"%__AppDir__%xcopy.exe" "%%B" "Destination\" /Options
Please note that it may be wise, if there's a chance that one or more of theses Folders do not exist, that you prepend using If Exist "%%B\". Importantly, if each of the lines containing the Folder paths, is space padded up to the end of its line, this solution will not work for you.
I would like to resolve simple problem - Saving to different file when loop repeats. I know im getting results because when I am doing >>file.txt
i am getting all restults into one file. It would be GREAT to save results to different files each time(and name this file by text from variable. but there is something wrong. It saves the results of last loop iteration.
#echo off
setlocal ENABLEDELAYEDEXPANSION
set vidx=0
for /F "tokens=1* delims=;" %%A in (list2.csv) do (
SET /A vidx=!vidx! + 1
set var!vidx!=%%A
rxrepl -f temp.txt -s "xNAMEx" -r "%%A">file___%var!vidx!%.txt
)
Try replacing this
file___%var!vidx!%.txt by this file___!var!!vidx!!!.txt
You don't need any variables to get the result you are looking for. Also, the * is usesless in "tokens=1*" if you never reference variable %%B. And "tokens=1" is the default. So all you need is:
for /F "delims=;" %%A in (list2.csv) do rxrepl -f temp.txt -s "xNAMEx" -r "%%A">"file___%%A.txt"
If you really want to build an "array" of var.N values, you can use FINDSTR to prefix each line with an incrementing number (line number).
for /F "tokens=1,2 delims=:;" %%A in ('findstr /n "^" list2.csv') do (
set "var.%%A=%%B"
set "var.cnt=%%A"
rxrepl -f temp.txt -s "xNAMEx" -r "%%B">"file___%%B.txt"
)
:: Display the "array" values
for /l %%N in (1 1 %var.cnt%) do echo var.%%N=!var.%%N!
Use just ...>"file___%%~A.txt" instead of erroneous >file___%var!vidx!%.txt
#ECHO OFF
SETLOCAL enableextensions enabledelayedexpansion
set vidx=0
for /F "tokens=1* delims=;" %%A in (list2.csv) do (
SET /A "vidx+=1"
set "var!vidx!=%%~A"
echo loopvar %%%% A=%%~A "file___%%~A.txt"
rem next line shows how to treat array-like names
call set "filenamepart=%%var!vidx!%%"
echo filenamepart=!filenamepart! "file___!filenamepart!.txt"
rem rxrepl -f temp.txt -s "xNAMEx" -r "%%A">"file___%%~A.txt"
)
I have this block of code:
#ECHO OFF
SET "SRCFOLDER=C:\Users\MyUserName\Desktop\PhotoTests"
SET "TEMPCODE=Hi"
ECHO %TEMPCODE%
ECHO.
FOR /F "tokens=*" %%G IN ('DIR /B %SRCFOLDER%') DO (
ECHO %%G
CALL tooltipInfo.bat %%G 19 | FIND /C "Star" > test.txt
SET /P TEMPCODE=<test.txt
ECHO %TEMPCODE%
ECHO.
)
SET /P TEMPCODE=<test.txt
ECHO %TEMPCODE%
ECHO.
PAUSE
I'm confused by the output as I noticed that the variable in the FOR loop is not overwritten by what I think should be the content of "test.txt", which will vary each time the FOR loop runs.
For the purpose of this example, the file tooltipInfo.bat will echo a text string like "1 Star" or "3 Stars" based on the rating recorded in the file's properties. The FIND statement should result in a "0" or "1" being saved into the test.txt file.
The output is:
Hi
Canon_Locked.JPG
Hi
Nikon_Locked.JPG
Hi
0
Press any key to continue . . .
May I know why the TEMPCODE variable isn't being overwritten in the loop and retains the original value of "Hi". However in the final block of code, it was able to read and echo out the actual content of the file.
This is a common mistake when using FOR and parentheses. The problem is that by default every variable between ( and ) is evaluated when the line is first read, and then re-used for each iteration of the FOR.
If the variable changes during the loop (via SET), then you will need to change % to ! for variables inside the parentheses, and also turn on delayed expansion using setlocal
SETLOCAL enabledelayedexpansion
FOR /F "tokens=*" %%G IN ('DIR /B %SRCFOLDER%') DO (
ECHO %%G
CALL tooltipInfo.bat %%G 19 | FIND /C "Star" > test.txt
SET /P TEMPCODE=<test.txt
ECHO !TEMPCODE!
ECHO.
)
I am really confused with something. I am making a batch file that can can display a specific line that I want. For example there is file hi.txt
Content of file -
ro.build.id=KOT49H
ro.build.display.id=XXX_ROM_v1
ro.build.version.incremental=eng.mudingyu.1408084583
ro.custom.build.version=XOLO_8x-1000_0815.v009
ro.internal.version=J608_XOLO_N1A_V0.8.7_S08015
ro.internal.version.rgk=J608_XOLO_N1A_V0.8.7_S08015
ro.build.version.sdk=19
ro.build.version.codename=REL
ro.build.version.release=4.4.4
ro.build.date=Fri Aug 15 14:39:45 CST 2014
ro.build.date.utc=1408084785
As here you can see the file content. Now say I want to print ONLY this piece of information on my screen when batch is executed
"4.4.4" from this line "ro.build.version.release=4.4.4"
I managed to pull of code for the 2nd line
ro.build.display.id=XXX_ROM_v1
When I execute batch I see this
XXX_ROM_V1
Code I used
set "build.prop="
for /F "skip=3 delims=" %%i in (WORKING_FOLDER\system\build.prop) do if not
defined build.prop set "build.prop=%%i"
echo.
echo "%build.prop%"
echo.
echo Enter the name you want to choose
set /p name=
echo Backing up old build.prop...
md C:\Kitchen\temp
copy C:\Kitchen\WORKING_FOLDER\system\build.prop C:\Kitchen\temp
cd C:\Kitchen\temp
cd C:\Kitchen\WORKING_FOLDER\system
build.prop.new (
for /f "tokens=1* delims==" %%A in (build.prop) do (
if "%%A" == "ro.build.display.id" (
echo ro.build.display.id=%name%
) else (
echo %%A=%%B
)
)
)
move /y build.prop.new build.prop >nul
build.prop.new (
for /f "tokens=1* delims==" %%A in (build.prop) do (
if "%%A" == "ro.build.id" (
echo ro.build.id=%name%
) else (
echo %%A=%%B
)
)
)
move /y C:\Kitchen\temp\build.prop.new
C:\Kitchen\WORKING_FOLDER\system\build.prop >nul
echo Changed value of ro.build.display.id to " %name% "
echo.
set "build.prop="
for /F "skip=3 delims=" %%i in (WORKING_FOLDER\system\build.prop) do if not
defined build.prop set "build.prop=%%i"
echo In build.prop now the current name of ROM is
echo.
echo Current ROM Name = %name%
Here as you see in first line I print the name using the line command function and also took input from user to change the name so it became easy to print the file name but in some other files the line "ro.build.display.id" is not always on 4th.
So my question is what logic or whatever can be done in order to print the particular term on screen that I wish to print without prompting user to enter new file name just print that specific piece of information
eg The OUTPUT I want
The Android version is "4.4.4"
EG Say I want to print "4.4.4" only from the file above
how can I do it?
Using findstr or anything please help really appreciated.
whew - that was a lot to read for a quite simple question.
for /f "tokens=2 delims==" %%i in ('find "ro.build.version.release" hi.txt') do set release=%%i
echo The Android version is "%release%"
Find the correct line and tokenize it with = as delimiter.
is there a way to transfer characters in the a plain .txt file.
I have a lot of entries in the .txt file and they are all in this format:
1 = Example,
2 = Example2,
3 = Example3...
what I need is a batch file to transfer "# =" to the right side of the string. So it looks like this:
Example = 1,
Example2 = 2...
Is it possible to that with a .bat file?
This will handle more than one word where you have Example...
#echo off
for /f "tokens=1,* delims== " %%a in (input.txt) do >>output.txt echo %%b = %%a
If you can use GNU sed:
sed "s/\(\S\+\)\s=\s\(\S\+\)/\2 = \1/" file
Something like this should work:
#echo off
pushd "C:\some\where"
for /f "tokens=1,2 delims==" %%a in (input.txt) do echo %%b = %%a
popd
Or use this to get rid of whitespace:
#echo off
setlocal EnableDelayedExpansion
pushd "C:\some\where"
for /f "tokens=1,2 delims==" %%a in (input.txt) do (
set "key=%%a"
set "val=%%b"
echo !val: =! = !key: =!
)
popd
To save the output to a file, call either script like this:
switch.cmd >output.txt