Replacing text in file at certain width

0

How can I can replace at at certain column positions?

Example: I want to replace columns 20-26 with 0s.

From:

12345678123456781234567812345678123456781234567812345678123456781234567812345678    

To:

12345678123456781234000000345678123456781234567812345678123456781234567812345678

This would be for each line in a file that could contain tens of thousands of lines like these.

divided

Posted 2010-10-27T19:30:54.260

Reputation: 245

any editor can do this (navigate to column 20, delete 6 (or 7?) characters, insert 6 (or 7) times 0). Are you trying to do it for a lot of lines in one file? For one or more line in several files, once? For one or more line in one or more files, many times? – Gilles 'SO- stop being evil' – 2010-10-27T20:57:50.077

Yes, this would be for each line in a text file that could contain tens of thousands of lines. Sorry for not being clear in my original post. – divided – 2010-10-28T13:02:30.570

Answers

0

I don't know of one specifically, but I just wrote one for you. It is written in autoit. You can download and compile it yourself using the code below, or you can download a comiled version here. If you want any changes made, just let me know, I'll see what I can do.

EDIT: if you need to do this with a file as well, let me know, I can make that change.

EDIT #2: I just updated it to do files (didn't know what formats you needed, but not sure how easy it will be to do anything but text/log files). It will report any line that is out of range. Also updated the link above with the new compiled version.

#include <GuiConstants.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <GuiEdit.au3>
#include <File.au3>

Dim $s_Name = "FileStringReplacer"

Main()

Func Main()
    $h_Parent = GuiCreate($s_Name,400,340)
    GuiCtrlCreateLabel("File to Edit",5,5,90,20)
    $in_File = GuiCtrlCreateInput("",10,25,380,20,$ES_READONLY)
    $bt_Browse = GuiCtrlCreateButton("Find File",10,50,380,25)
    GuiCtrlCreateLabel("Request Status",5,80,90,20)
    $ed_Status = GuiCtrlCreateEdit("",10,100,380,100,$ES_READONLY + $WS_VSCROLL)
    GuiCtrlCreateLabel("Start Point",5,210,50,20)
    $in_Start = GuiCtrlCreateInput("",60,210,25,20)
    GuiCtrlCreateLabel("Stop Point",95,210,50,20)
    $in_Stop = GuiCtrlCreateInput("",150,210,25,20)
    GuiCtrlCreateLabel("Text to Insert",5,240,90,20)
    $in_String = GuiCtrlCreateInput("",10,260,380,20)
    $bt_Replace = GuiCtrlCreateButton("Replace",10,290,380,25)
    GuiSetState()
    Do
        $Msg = GUIGetMsg()

        If $Msg = $bt_Browse Then
            $h_File = FileOpenDialog("File to Modify",@MyDocumentsDir,"Text (*.txt;*.log)", 3)
            GuiCtrlSetData($in_File,$h_File)
        EndIf

        If $Msg = $bt_Replace Then
            GuiCtrlSetData($ed_Status,"")
            If GuiCtrlRead($in_File) <> "" Then
                If IsInt(Int(GuiCtrlRead($in_Start))) and IsInt(Int(GuiCtrlRead($in_Stop))) and Int(GuiCtrlRead($in_Start)) <> 0 and Int(GuiCtrlRead($in_Stop)) <> 0 Then
                    GuiCtrlSetState($bt_Browse,$GUI_DISABLE)
                    GuiCtrlSetState($bt_Replace,$GUI_DISABLE)
                    $h_File = FileOpen(GuiCtrlRead($in_File))
                    $i = 1
                    $s_Line = ""
                    While 1
                        $s_Line = FileReadLine($h_File,$i)
                        If @error Then
                            ExitLoop
                        EndIf
                        If StringLen($s_Line) > GuiCtrlRead($in_Stop) - GuiCtrlRead($in_Start) Then
                        $stringright = StringTrimLeft($s_Line,GuiCtrlRead($in_Stop))
                        $stringleft = StringLeft($s_Line,GuiCtrlRead($in_Start) -1 )
                        $newstring = $stringleft & GuiCtrlRead($in_String) & $stringright
                        _FileWriteToLine(GuiCtrlRead($in_File), $i, $newstring, 1)
                        Else
                            _GUICtrlEdit_AppendText(GuiCtrlGetHandle($ed_Status), @CRLF & "Edit to line " & $i & " failed, specified position is out of range")
                        EndIf
                        $i = $i + 1
                    WEnd
                    FileClose($h_File)
                    GuiCtrlSetState($bt_Browse,$GUI_ENABLE)
                    GuiCtrlSetState($bt_Replace,$GUI_ENABLE)
                Else
                    GuiCtrlSetData($ed_Status,"Error 102" & @CRLF & "Start and stop points must be numbers")
                EndIf
            Else
                GuiCtrlSetData($ed_Status,"Error 101" & @CRLF & "You must specify a file to edit")
            EndIf
        EndIf
        Until $Msg = $GUI_EVENT_CLOSE
    GUIDelete($h_Parent)
EndFunc

MaQleod

Posted 2010-10-27T19:30:54.260

Reputation: 12 560

If you could make the change, that would be great. This would be for each line in a text file that could contain tens of thousands of lines. – divided – 2010-10-28T13:03:17.763

Just updated it to do .txt and .log files. I might be able to add other formats depending on what you need. – MaQleod – 2010-10-28T23:54:14.387

1

It should be trivial in any text editor. In gvim for the current line the command might be 020lc6l000000<esc>

Is there any special reason you wish to avoid regular expressions?


EDIT

Here's a statement containing a simple regular expression: s/^(.{19}).{6}/${1}000000/

It means search for

^      start at the beginning of a line
(      remember stuff found between parentheses
.      any single character
{19}   exactly 19 of them
)      end of the part we want to remember
.{6}   followed by any 6 characters which we won't remember

and replace them with

${1}   the first set of characters we remembered using () - 19 chars
000000 followed by six zeros (replacing the .{6} we ignore)

normally you'd write ${1} as $1 but when it is followed by digits you have to use {} to distinguish between the tenth remembered part $10 and the first part $1 followed by a literal 0.

Used like this

perl -pie 's/^(.{19}).{6}/${1}000000/' foo.txt bar.txt any*.txt

to do in-place editing of all lines in any number of files. But test it on a copy of the file first!

RedGrittyBrick

Posted 2010-10-27T19:30:54.260

Reputation: 70 632

My special reason is that I don't like them! In reality, I just haven't had too much experience with them and at this point, I could never write one on my own. – divided – 2010-10-28T13:06:46.977

Regular expressions can be complicated and hard to understand. However you can also learn just a few basic elements and use them in a simple but useful way. Example in edited answer above ... – RedGrittyBrick – 2010-10-28T14:03:44.440

Thanks for the explanation. Is there any way that I could use the expression to start at a certain position in each line? This is a fixed-width file and the characters that need to be replaced in each line are at the same position. – divided – 2010-10-28T14:48:57.220

1^(.{19}) effectively means start at position 20. – RedGrittyBrick – 2010-10-28T15:39:34.130

0

Chris

Posted 2010-10-27T19:30:54.260

Reputation: 1 093

Thanks for the reply. From this page, I don't see anything that explicitly states that I can replace characters at a certain line position. Would I need a regular expression to do that? I'd like to stay away from regular expressions if possible. – divided – 2010-10-27T20:08:42.327

0

Try this:

sed -i 's/^\(.\{19\}\).\{7\}/\10000000/' inputfile

or

sed -ri 's/^(.{19}).{7}/\10000000/' inputfile

Paused until further notice.

Posted 2010-10-27T19:30:54.260

Reputation: 86 075

Thanks for the reply, but I am running Windows 7. – divided – 2010-10-28T13:05:49.257

@divided: That's something you should mention in your question. – Sasha Chedygov – 2010-10-29T00:07:50.160

@divided: There are at least a few ways sed can be used on a Windows system including GnuWin32 and UnxUtils.

– Paused until further notice. – 2010-10-29T01:54:24.443

0

Vim can do this very easily.

Open the file in Vim, then type:

:% normal 019l6r0<Enter>



:% normal means do the next commands on every line in the file.

0 means: move the cursor to the beginning of the line.

19l means: move the cursor right 19 times

6r0 means: replace the next 6 characters with 0


I know the commands might look a bit cryptic at first. But you only need to learn a few very simple commands to do what you need.

0 moves the cursor to the beginning of the line
$ moves the cursor to the end of the line

h moves the cursor to the left
j moves the cursor down
k moves the cursor up
l moves the cursor to the right

r replaces the character under the cursor with the next character pressed

Type a number before any command to have that command done "number" times.

:% normal <list of commands><Enter> does a list of commands on ever line in the file


You can also record a bunch of edits then replay the same edits on every line of the file.

Record commands.

qa<commands>q

then, replay the commands on every line of the file.

:% normal @a<Enter>

Jay

Posted 2010-10-27T19:30:54.260

Reputation: 614

This does work, but I'd like to stay away from installing another program if possible. – divided – 2010-10-29T14:57:18.170