views:

2128

answers:

11

Hi guys Havin' problems tryin' to get the string after the : in the following two lines into two seperate variables from the bottom of a text file called file.txt for example

Number of files to delete:  27 Total
Total size of files to delete: 1,427 KB

I just want the 27 in one variable, and the 1,427 in another. These are randomly generated from a scan, and could include more digits. Hope you understand :)

Thanks for yall your help

Batch file please, i am using windows

A: 

I assume You need this to be done in pure bash.

#!/bin/bash
S="$(<testfile.txt)" # load the data

A="${S#*:}" # remove everything before the first : (including it)
A="${A%%Total*}" # remove everything after the first "Total" (including it)

B="${S##*:}" # remove everything before the last : (including it)
B="${B% *}" # remove everything after the last space (including it)

A="${A// }" # remove all spaces
B="${B// }"

echo "-$A-" # print results (showing that there are no spaces in it)
echo "-$B-"

I encourage You to explore Parameter Expansion section of man bash. You will find numerous usefull tricks there.

Reef
I've ran some tests, this script (with `echo` removed) executes 3500times/s on my box, 22000 times/s when loading the file is done only once. Looking forward for other solutions with head, tail, cut and cat ;)
Reef
This looks like an excellent bash answer, but I think he might be on Windows. See batch and cmd tags
Andy
A: 

I am using Windows, and would prefer it to be purely in cmd :)

I would of thought the following would of workedfor /F "tokens=2 delims==" %I in ('findstr "Number of" text.txt') do echo %IDon't get any response though..
+2  A: 

Something like this should work:

@echo off
setlocal enableextensions enabledelayedexpansion

:: Get the number of lines in the file
set LINES=0
for /f "delims==" %%I in (file.txt) do (
    set /a LINES=LINES+1
)

:: Parse the last 2 lines and get the numbers into variable NUMS
set /a LINES=LINES-2
for /f "skip=%LINES% delims=" %%L in (file.txt) do (
    for /f "tokens=1-2* delims=:" %%A in ("%%L") do (
        for /f "tokens=1-2*" %%N in ("%%B") do set NUMS=!NUMS!%%N;
    )

)

:: Parse variable NUMS
for /f "tokens=1-2* delims=;" %%A in ("%NUMS%") do (
    set NUM_FILES=%%A
    set TOTAL_SIZE=%%B
)

@echo Number of files     = %NUM_FILES%
@echo Total size of files = %TOTAL_SIZE%
Patrick Cuff
A: 

I dont have enough rep to comment so i will have to post it into an answer. Thankyou for your contributions there mate, but unfortunately im unable to test, as I'm gettin' this error here when running the batch script. I've uploaded a screenshot. I copied and pasted your code directly, and only edited the filename portion.

http://tinypic.com/view.php?pic=2powpsp&amp;s=5

What flavor of Windows are you using? How are you getting a command prompt, via cmd.exe or command.com?
Patrick Cuff
From your screen shot it also looks like there's some unprintable character before the '@'; that may be throwing things off.
Patrick Cuff
Windows Vista Home Basic SP1. Yeah it does look like some unprintable character before the @, but its not. If I take away the @; the error comes up with an 'e' instead of the @.I don't know whats happenin', other batch files seem to work fine.Getting command prompt via cmd.exe.Tried via command.com too. Same result
A: 

@Patrick Cuff

An update.. It is not your script that is the problem. I tried a batch file with just @echo off in it and ran it and I get the same error; so I know its not your script that it is doing it. Further more; I have no clue to why it is doing this? Maybe you've come across somethin' similar before?

I haven't done much batch scripting before and have never seen this. I have piped the set command to a txt file and copied and pasted it below. It doesn't seem like anythin' has changed to me.

ALLUSERSPROFILE=C:\ProgramData
APPDATA=C:\Users\Methical\AppData\Roaming
CLASSPATH=.;C:\Program Files\Java\jre6\lib\ext\QTJava.zip
CommonProgramFiles=C:\Program Files\Common Files
COMPUTERNAME=NEMESIS
ComSpec=C:\Windows\system32\cmd.exe
DFSTRACINGON=FALSE
FP_NO_HOST_CHECK=NO
HOMEDRIVE=C:
HOMEPATH=\Users\Methical
LOCALAPPDATA=C:\Users\Methical\AppData\Local
LOGONSERVER=\\NEMESIS
NUMBER_OF_PROCESSORS=1
OS=Windows_NT
Path=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files\QuickTime\QTSystem\
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 6 Model 15 Stepping 13, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=0f0d
ProgramData=C:\ProgramData
ProgramFiles=C:\Program Files
PROMPT=$P$G
PUBLIC=C:\Users\Public
QTJAVA=C:\Program Files\Java\jre6\lib\ext\QTJava.zip
SystemDrive=C:
SystemRoot=C:\Windows
TEMP=C:\Users\Methical\AppData\Local\Temp
TMP=C:\Users\Methical\AppData\Local\Temp
TRACE_FORMAT_SEARCH_PATH=\\NTREL202.ntdev.corp.microsoft.com\4F18C3A5-CA09-4DBD-B6FC-219FDD4C6BE0\TraceFormat
USERDOMAIN=Nemesis
USERNAME=Methical
USERPROFILE=C:\Users\Methical
windir=C:\Windows
That looks OK.Are you using a localized version of Vista (non-US)?Just for laughs, change the extension of the script from .bat to .cmd and see what that does.Do any .bat scripts work for you?
Patrick Cuff
A: 

@Patrick Cuff

I realised that I had been always editing the same batch file. So I deleted it. Started a new one from scratch thru notepad, saved it as a .bat and ran it. No errors this time. So I copied and pasted your code into a new batch file, and ran it.

Well.. It ran, but there was an error. Havin' problems embedding the picture; but heres the link.

screenshot

@jimbob15; change `@echo OFF` to `@echo ON` and see where the error is occurring. I can run this on XP and Server 2003 with no problems.
Patrick Cuff
A: 

@Patrick Cuff I am running Windows Vista Home Basic SP1. I would like it compatible for Vista and XP if possible.

I changed the echo off to on, and ive uploaded another screenshot for u. And also the relevant text file that im tryin' to extract the values from.

clean.txt

Screenshot2

The output for the first `for` command should be "D:\>for /F "skip=280 delims=" %L in (clean.txt) do (for /F "tokens=1-2* delims=:" %A in ("%L") do (for /F "tokens=1-2*" %N in ("%B") do set NUMS=!NUMS!%N; ) )". It looks like the LINES var is not being set. Try changing `delims==` to `delims=`.
Patrick Cuff
I havne't tested it yet, as im on my way to work. just checkin' for responses. But from what i understand, this code will only work if there is 280 lines.. What happens if there was only a 100 lines?This is just a log file from a cleanup utility im using. On a real dirty machine i could easily expect over 1000 lines...Thanks for all ur help Patrick. I'm off to work now, I'll catch up with u later.
@jimbob15; the 280 lines is for the clean.txt file you provided and is computed for whatever file you specify. If you have a file with 10,000 lines this value should be 10,000. It's not hard coded in the script. When you turn `@echo ON` the command output is printed to the console window. From your output it looked like the `for` command output was missing the value of the `LINES` variable, which is probably where the problem is.
Patrick Cuff
AHhhh, gotcha. It was 5am when I read your comment this mornin; just had a glance @ it. I didn't see your D:> before that lol; else I would've realised that it wasn't hard-coded in. I've got a bit of study to do first, (@ course at the moment); I'll test the script when I get home tonight. Thanks, as always.
Nah mate, just had a test and still doesn't want to work for me, even after changing the delims like u suggested. Uploaded another pic,http://i43.tinypic.com/9rsuba.jpg
My guess is that the script can't find the file 'clean.txt'; where does it reside? Try specifying the full path rather than just the file name.
Patrick Cuff
I think that is the problem. I specified the full path, and put parenthesis around still didn't work. I added a two 'echo %LINES%' in the script. And get the values 0 and -2. So I'm guessin' its not reading the text file. I've uploaded another txt file for you to have a look @ if you wanted.. http://i39.tinypic.com/169ji1z.jpg
In the first `for` command do you have `set /a LINES=LINES+1` or `set /a LINES=%LINES%+1`? You should have the first one. When I change my script to the second I get the errors your seeing.
Patrick Cuff
Within **for loops**, try the following incrementation style: set /a var+=1. With this, you don't need to re-read the variable content thus don't need the setlocal.
Jay
A: 

This is my full batch file;

@echo on
setlocal enableextensions enabledelayedexpansion

:: Get the number of lines in the file
set LINES=0
for /f "delims==" %%I in (D:\clean.txt) do (
    set /a LINES=LINES+1
    echo %LINES%
)

:: Parse the last 2 lines and get the numbers into variable NUMS
set /a LINES=LINES-2
echo %LINES%
for /f "skip=%LINES% delims=" %%L in (D:\clean.txt) do (
    for /f "tokens=1-2* delims=:" %%A in ("%%L") do (
        for /f "tokens=1-2*" %%N in ("%%B") do set NUMS=!NUMS!%%N;
    )

)

:: Parse variable NUMS
for /f "tokens=1-2* delims=;" %%A in ("%NUMS%") do (
    set NUM_FILES=%%A
    set TOTAL_SIZE=%%B
)

@echo Number of files     = %NUM_FILES%
@echo Total size of files = %TOTAL_SIZE%

You can see where i put the extra echoes in, too see the value of the variable and i get the previous screenshot. Why does it work for you and not me? thats not fair lol I'm running Vista Home Basic SP1 32-bit

The `echo %LINES%` inside the `for` loop are evaluated before the `for` command is executed, so will always display zero. To see if `LINES` is being incremented use delayed expansion; `echo !LINES!`. Other than that, your script works for me. I don't have access to a Vista system, but I will run this on Windows 7 and see what happens.
Patrick Cuff
Both scrips work for me on Windows 7. See my newest answer for a different possible solution.
Patrick Cuff
A: 

It looks like you're having some problem with reading through the whole file to get the number of lines. This solution will find just the strings you're interested in and get the values:

@echo off
setlocal enableextensions enabledelayedexpansion

:: Get number of files to delete.
for /f "usebackq tokens=1-7" %%A in (`findstr /b "Number of files to delete:" file.txt`) do (
    set NUM_FILES=%%F
)

:: Get total size of files.
for /f "usebackq tokens=1-8" %%A in (`findstr /b "Total size of files to delete:" file.txt`) do (
    set TOTAL_SIZE=%%G
)

@echo Number of files     = %NUM_FILES%
@echo Total size of files = %TOTAL_SIZE%

If the strings with the number of files and total size ever change, you'll have to change the script accordingly.

Patrick Cuff
A: 

Sorry for another answer, but I can comment sometimes, but othertimes not. Or maybe i can only comment to my own answers...

Anyway, ran your latest script, still no variables appear.. I have asked on another forum for an answer for this to, but still havin' no luck there.. Here is an answer I got in a reply to an email from someone I asked to help me..

Salve (Hi) Tim, sorry you had to wait for my response, but other than the time-lag I faced a strange issue with your text file. What I discovered explains the weird behavior you reported while running my original script. Your text file is encoded in Unicode-like format but missing the 0xFF-0xFE marker in the first two bytes. That prevents Windows correctly processes its content. The same happened when you saved my batch code. Notepad gives you a broad chance to open the file even if it is not correctly encoded, but in console window the rules are more strict.
When you save a text file ensure to save in Unicode or (better) ANSI format. I don't know how you generated such a format that, I repeat, doesn't belong to standard Windows' formats.

A: 

jimbob, here is what I came up with:

delfiles.cmd

@echo off
set file=clean.txt
call :grep "Number of files to delete:"
set files=%grep%
call :grep "Total size of files to delete:"
set size=%grep%

echo %Files% files of a total size of %size% are to be deleted.
exit /b 0

:grep
    setlocal
    for /F "tokens=2 delims=:" %%i in ('findstr /i /c:"%~1" "%file%"') do (
      for /F "tokens=1 delims= " %%j in ("%%i") do set _find=%%j
    )
    endlocal& set grep=%_find%
    exit /b 0

This is a re-usable script, as the file and strings can be changed with the same results. I copied/pasted your example and it worked good.

@Patrick Cuff: you might run into problems finding a whole string without the /c:".." part. Might have been a part of the problem, but then maybe my script will give the same results/problems... Live and learn I guess.

______Notes__________
set file= : Set this to the file (and path, if needed) of the file to be scanned.
call :grep "string" : Call the :grep function with the string to find.
set var=%grep% : Set a variable (here files and size) to the answer from :grep.

:grep function: It first looks within the %file% for the "%string%", then parse it at the ':' character, keeping the right-hand part. It then parse it again with 'spaces' and keep the first word. The function returns the variable %grep% which contain the found string.

As with my usual answers, I hope this helps.

Jay