Sign in to follow this  
Followers 0
emendelson

Get line number of string in text file?

8 posts in this topic

Is there a routine in AutoIt that will read a text file and tell me the line number (or numbers) of any line that contains a specific string?

I am looking for this (or something like it) because I want to open %systemroot%\system32\autoexec.nt and find any line that contains "tame-nt.com" (any line which does NOT start with REM or a colon but contains that string), and then temporarily add REM the start of that line (or lines) and write the file to disk; I then want to perform some other operations in a script; and finally I want to remove the REM that I added to the line so that the autoexec.nt file ends up the way it started. (The reason for this that the current version of the Tame utility which speeds up 16-bit DOS applications - see www.tamedos.com - crashes when certain operations are performed by a script that I've been using for years, and I want to prevent Tame from loading when those specific operations are performed, but only when those operations are performed.)

The easiest way to do this seems to be to know the line number and use FileWrite to modify the line. Or is there a simpler method that I haven't been able to think of?

Thanks for any help.

Share this post


Link to post
Share on other sites



Is there a routine in AutoIt that will read a text file and tell me the line number (or numbers) of any line that contains a specific string?

I am looking for this (or something like it) because I want to open %systemroot%\system32\autoexec.nt and find any line that contains "tame-nt.com" (any line which does NOT start with REM or a colon but contains that string), and then temporarily add REM the start of that line (or lines) and write the file to disk; I then want to perform some other operations in a script; and finally I want to remove the REM that I added to the line so that the autoexec.nt file ends up the way it started. (The reason for this that the current version of the Tame utility which speeds up 16-bit DOS applications - see www.tamedos.com - crashes when certain operations are performed by a script that I've been using for years, and I want to prevent Tame from loading when those specific operations are performed, but only when those operations are performed.)

The easiest way to do this seems to be to know the line number and use FileWrite to modify the line. Or is there a simpler method that I haven't been able to think of?

Thanks for any help.

There are a couple of ways to do ths but no single function that will return the line number. Probably the easiest is to use _FileReadToArray(), correct the elements (see StringInStr() for this) and then _FileWriteFromArray(). My personal preference would be to use FileRead() followed by StringRegExpReplace() to correct the strings then FileWrite(). Be carefull when you add the REM to those lines if there are already REMed lines containing that string. If you attempt to write a script to undo the changes you will also remove the existing REMs. I would use "REM ~" or something along those lines so that you can undo it with a simple StringReplace().

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

This is a non-conventional method, but this example appears to work.

;
#include <File.au3>
#include <array.au3>

Local $sFileName = "test.txt"
Local $searchStr = "sk"

$aResult = _LineNumsOfSearchStr($sFileName, $searchStr, False)

_ArrayDisplay($aResult)

; Returns array of found line numbers that contain $searchStr contents.
; Optional delete found line from file.
Func _LineNumsOfSearchStr($sFileName, $searchString, $bDeleteLine = False)
    Local $location, $aCurrentLineNum, $iCurrentLineNum, $sFile, $iOccur = 1, $sRes = ""
    If FileExists($sFileName) = 0 Then Return 1
    Do
        $sFile = FileRead($sFileName)
        $location = StringInStr($sFile, $searchString, 0, $iOccur) ; Find the $iOccur occurrence of the "substring"

        If $location > 0 Then
            $aCurrentLineNum = StringRegExp(StringRegExpReplace($sFile, "(?s)(.{" & $location & "})(.*)$", "\1"), "(?s)(\v+)", 3) ;Find line number
            $iCurrentLineNum = UBound($aCurrentLineNum) + 1 ; Line number

            ;ConsoleWrite("CharPos: " &  $location & "   Ln: " & $iCurrentLineNum & @CRLF)
            $sRes &= $iCurrentLineNum & "|"
            If $bDeleteLine Then
                _FileWriteToLine($sFileName, $iCurrentLineNum, "", 1) ; Remove found line from file.
            Else
                $iOccur += 1
            EndIf
        Else
            ExitLoop
        EndIf
        Sleep(10)
    Until 0
    ;ShellExecute($sFileName)
    Return StringSplit(StringTrimRight($sRes, 1), "|")
EndFunc   ;==>_LineNumsOfSearchStr
;

Edit: Removed Quote.

Edited by Malkey

Share this post


Link to post
Share on other sites

Actually I was just giving this somemore thought and it's okay to put a REM ~ infront of an existing REM statement so that makes it simple.

$sFile = @SystemDir & "\autoexec.nt"
$sStr = FileRead($sFile)
$sStr = StringRegExpReplace($sStr, "(?i)(.*tame\-nt\.com.*)", "REM ~$1")
If @Extended Then
    $hFile = FileOpen($sFile, 2)
    FileWrite($hFile, $sStr)
    FileClose($hFile)
EndIf

To Undo the changes would be similar

$sFile = @SystemDir & "\autoexec.nt"
$sStr = FileRead($sFile)
$sStr = StringReplace($sStr, "REM ~", "")
If @Extended Then
    $hFile = FileOpen($sFile, 2)
    FileWrite($hFile, $sStr)
    FileClose($hFile)
EndIf

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites

Actually I was just giving this somemore thought and it's okay to put a REM ~ infront of an existing REM statement so that makes it simple.

Many, many thanks - this is simple and elegant and does EXACTLY what I was hoping to find. I'll incorporate it in my script immediately.

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Many, many thanks - this is simple and elegant and does EXACTLY what I was hoping to find. I'll incorporate it in my script immediately.

Glad it helped.

Tip: If you are incorporating that into a full script then put the code into separate functions

Func _RemLines()
     ;; First code block in here
EndFunc

Func _UnRemLines()
    ;; Second code block
EndFunc

You could also make those functions more usable. Instead just limiting them to tame-nt.com set a parameter in the first function that tells te RegExpReplace what to search for. It will only take one extra line of RegExpReplace code to escape any characters that have to be escaped. If you did that you could call the function like this

_RemLines("tame-nt.com")

Func _RemLines($sFind)
     ;; Line to escape characters, I think this will work fine
     $sFind = StringRegExpReplace($sFind, "([[:punct:]])", "\\$1")
     ;; First code block in here with the line
     $sStr = StringRegExpReplace($sStr, "(?i)(.*tame\-nt\.com.*)", "REM ~$1")
     ;; changed to 
     ;; $sStr = StringRegExpReplace($sStr, "(?i)(.*" & $sFind & ".*)", "REM ~$1")
EndFunc
Edited by GEOSoft

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites

Thanks again for that - I had already put the code in function blocks (I need to use each block four times in this script), but hadn't thought about using tame-nt.com as a parameter to make it easier to re-use the code. Will do that now - and again, many thanks for elegant code that does precisely what was needed. I think these snippets would be useful to other people also.

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

@Malkey @Geosoft you guys are awesome. for the first time I have seen regex being used to extract line nos. I never knew this was possible.

From me 5 stars.

Regards

Deltar

Edited by deltar

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0