Jump to content

Replace text in a file


Recommended Posts

Hi,

I'd like to find out how to replace text in a file only if it's within double quotes. An example would be:

This is text in the file. "This is where I need CRLF replaced by some text" CRLF

I'd like to replace the CRLF because it's between double quotes. I don't want to replace the CRLF at the end.

Thank you,

Docfxit

Link to comment
Share on other sites

  • Moderators

I could of sworn I saw this very subject 1 or 2 days ago?... was there an answer on that one?

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

are there several lines like that? or something like this?

"This is where I need CRLF replaced by some text" CRLF " more stufff here in another set of quotes CRLF and has more stuff to replace" CRLF "etc."

If the above example is how your file looks then you may need to go one character at a time since all of the "CRLF"s are inbetween quotes.

Link to comment
Share on other sites

See in help file this function _ReplaceStringInFile().

Or you can use my version on this func:

$Ret = ReplaceText("C:\test.txt", "Old Text", "New Text")
ConsoleWrite($Ret & @LF & @extended)

Func ReplaceText($FileName, $OldText, $NewText) 
    If Not FileExists($FileName) Then Return SetError(1, 0, -1)
    If $OldText = "" Then Return SetError(2, 0, 0)
    
    Local $hFile = FileOpen($FileName, 0)
    Local $VarToWrite = FileRead($hFile)
    FileClose($hFile)
    If Not StringInStr($VarToWrite, $OldText) Then Return SetError(3, 0, 0)
    
    Local $ReplStr = StringReplace($VarToWrite, $OldText, $NewText)
    Local $Extended = @extended
    
    Local $hFileW = FileOpen($FileName, 2)
    FileWrite($hFileW, $ReplStr)
    FileClose($hFileW)
    Return SetError(0, $Extended, 1)
EndFunc

 

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

Spoiler

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

 

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Link to comment
Share on other sites

Open help file and look for FileRead, _StringBetween, StringInStr, StringReplace and FileWrite.

Thanks for the reply. The way I see it I can't use any of these except FileRead and FileWrite because I need to replace the CRLF if there is double quotes around it.

Thank you,

Docfxit

Link to comment
Share on other sites

I could of sworn I saw this very subject 1 or 2 days ago?... was there an answer on that one?

Kinda. The one you probably saw needs this as an answer. This is much simpler and to the point. No one was answering the other one.

Thank you,

Docfxit

Link to comment
Share on other sites

are there several lines like that? or something like this?

"This is where I need CRLF replaced by some text" CRLF " more stufff here in another set of quotes CRLF and has more stuff to replace" CRLF "etc."

If the above example is how your file looks then you may need to go one character at a time since all of the "CRLF"s are inbetween quotes.

Yes I haven't found anything that would find something in between quotes.

The problem is when the record is read in it will have the first quote. Because it's a CRLF AutoIt will have to read in the next record (which is really part of the first record.) until it finds the next quote.

Thank you,

Docfxit

Link to comment
Share on other sites

Any chance you could post a section of the file?

Sure. This is one record but it reads in as three records because of the CRLF's

LastName,FirstName,"Address1

Address2",City,State,ZipCode,Country,,,,,,,,,,,,,Home,,Work,,Cell1,,Fax,,Email1,,Email2,,,,,,"Divorced

Died"

Thanks for looking at it.

Docfxit

Link to comment
Share on other sites

See in help file this function _ReplaceStringInFile().

Or you can use my version on this func:

Sample function removed because of a board error

The problem the way I see it is I can't use this because I don't know if the CRLF that I need to replace is between double quotes or if it marks the end of the record.

Thank you,

Docfxit

Edited by docfxit
Link to comment
Share on other sites

Sure. This is one record but it reads in as three records because of the CRLF's

LastName,FirstName,"Address1

Address2",City,State,ZipCode,Country,,,,,,,,,,,,,Home,,Work,,Cell1,,Fax,,Email1,,Email2,,,,,,"Divorced

Died"

Thanks for looking at it.

Docfxit

What comes after this one record - is it a blank line? If so, one solution may be to use FileRead to read two lines. If second line is not a blank line, append second to first and read next. Keep going until a blank line is encountered. At that point, process the accumulated records (all appended into a single string), then start over (read next two lines etc. etc.)

Edit: If next record is not a blank record, then you could use StringRegExp to check if the record ends with an unterminated double-quoted string, and assume that if it does, the rest is in the next record:

$fResult = StringRegExp($sString, '^[^"]*?(?:["][^"]*?["][^"]*?)*?["][^"]*?$', 0); $fResult is TRUE if unterminated string in line

the following should only give console output on an unterminated double-quoted string (last test) - it works on my machine

$sUnterminatedDQ = '^[^"]*?(?:["][^"]*?["][^"]*?)*?["][^"]*?$'
$sString = 'no double-quoted string in the line'
$fResult = StringRegExp($sString, $sUnterminatedDQ, 0)
if @error or $fResult Then ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $fResult = ' & $fResult & @crlf & '>Error code: ' & @error & ', Extended: ' & @extended & @crlf);### Debug Console
$sString = 'double-quoted "string" in the line'
$fResult = StringRegExp($sString, $sUnterminatedDQ, 0)
if @error or $fResult Then ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $fResult = ' & $fResult & @crlf & '>Error code: ' & @error & ', Extended: ' & @extended & @crlf);### Debug Console
$sString = '"double-quoted string" at start'
$fResult = StringRegExp($sString, $sUnterminatedDQ, 0)
if @error or $fResult Then ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $fResult = ' & $fResult & @crlf & '>Error code: ' & @error & ', Extended: ' & @extended & @crlf);### Debug Console
$sString = 'double-quoted string "at the end"'
$fResult = StringRegExp($sString, $sUnterminatedDQ, 0)
if @error or $fResult Then ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $fResult = ' & $fResult & @crlf & '>Error code: ' & @error & ', Extended: ' & @extended & @crlf);### Debug Console
$sString = 'multiple "double-quoted" strings "in the" line'
$fResult = StringRegExp($sString, $sUnterminatedDQ, 0)
if @error or $fResult Then ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $fResult = ' & $fResult & @crlf & '>Error code: ' & @error & ', Extended: ' & @extended & @crlf);### Debug Console
$sString = 'unterminated "double-quoted string in the line'
$fResult = StringRegExp($sString, $sUnterminatedDQ, 0)
if @error or $fResult Then ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $fResult = ' & $fResult & @crlf & '>Error code: ' & @error & ', Extended: ' & @extended & @crlf);### Debug Console

The pattern works as follows:

^[^"]*? - matches anything up to the first double-quote

(?: - starts a group (the '?:' tells StringregExp not to remember the matching text

["] - matches an opening double quote

[^"]*? - matches anything between the double quotes

["] - matches a closing double quote

[^"]*? - matches any characters up to the next double quote

)*? - finishes the group, and tells RegExp to look for zero or more of these groups (DQ string followed by other chars)

["] - matches an unmatched double quote

[^"]*?$ - matches remaining characters up to the end of the line

All of the stuff up to the "unmatched double quote" is necessary to handle correctly matched double quotes in the line ...

Edited by MisterBates
Link to comment
Share on other sites

What comes after this one record - is it a blank line? If so, one solution may be to use FileRead to read two lines. If second line is not a blank line, append second to first and read next. Keep going until a blank line is encountered. At that point, process the accumulated records (all appended into a single string), then start over (read next two lines etc. etc.)

I don't have a blank line.

Edit: If next record is not a blank record, then you could use StringRegExp to check if the record ends with an unterminated double-quoted string, and assume that if it does, the rest is in the next record:

$fResult = StringRegExp($sString, '^[^"]*?(?:["][^"]*?["][^"]*?)*?["][^"]*?$', 0); $fResult is TRUE if unterminated string in line
This is really supper. You are really great for putting this together for me. It works perfectly. I had no idea this could be done in one line like this. I was ready to create a few loops to solve it.

Thank you very very much,

Docfxit

Link to comment
Share on other sites

This is really supper. You are really great for putting this together for me. It works perfectly. I had no idea this could be done in one line like this. I was ready to create a few loops to solve it.

Thanks - always good to get feedback (and thanks) :rolleyes:

To be honest, I wasn't sure it could be done with RegExps, and struggled for a while with CRLF inside double quotes vs. outside double quotes (where there might not be a closing double quote). But once you posted data showing that a single line could be split over 2-3 lines in the file, that made it much easier to visualise.

Edit: BTW, if you're working with CSV files, you might want to split the input (once you've reconstructed the record) into its fields. The Following RegExp (courtesy Jim Weirich) does just that. You need to use StringRegExp with flag=3 as follows:

$sPattern = '([^",]*|"(?:[^"]|"")*")(?:,|\Z)'
$sTestRecord = ',,,"""",,,"hello",356.3,,,"some more string data"'
$asFields = StringRegExp($sTestRecord, $sPattern, 3)

One curiosity while testing - if the input record ends with a double-quoted field, the array returned by StringRegExp contains one extra field at the end (can't figure out why).

Parsing the CSV records this way takes account of null fields, of commas inside double quotes, and of pairs of double quotes inside double quotes. It also enables you to know when you've fully reconstructed a record, even if @crlf occurs in a non-Double-Quoted field, simply by testing that the number of fields is high enough.

See you in the forums!

Edited by MisterBates
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...