以特定宽度替换文件中的文本

以特定宽度替换文件中的文本

我怎样才能在某些列位置进行替换?

例如:我想用 0 替换第 20 至 26 列。

从:

12345678123456781234567812345678123456781234567812345678123456781234567812345678    

到:

12345678123456781234000000345678123456781234567812345678123456781234567812345678

这将针对文件中的每一行,该文件可能包含数万行这样的行。

答案1

我不知道具体哪一种,但我刚刚为你写了一篇。它写于自动。您可以使用下面的代码自行下载并编译,也可以下载编译版本这里。如果您希望进行任何更改,请告诉我,我会尽力为您效劳。

编辑:如果您也需要对文件执行此操作,请告诉我,我可以进行更改。

编辑 #2:我刚刚更新了它以处理文件(不知道您需要什么格式,但不确定除了文本/日志文件之外,处理其他文件是否容易)。它会报告超出范围的任何行。还使用新编译的版本更新了上面的链接。

#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

答案2

在任何文本编辑器中这应该很简单。在 gvim 中,对于当前行,命令可能是020lc6l000000<esc>

您希望避免使用正则表达式有什么特殊原因吗?


编辑

以下是包含简单正则表达式的语句:s/^(.{19}).{6}/${1}000000/

这意味着搜索

^      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

并将其替换为

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

通常你会写成${1}但是$1当它后面跟着数字时你必须使用 {} 来区分记住的第十部分 $10 和第一部分 $1 后面跟着文字 0。

像这样使用

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

对任意数量的文件中的所有行进行就地编辑。但请先在文件的副本上进行测试!

答案3

答案4

Vim可以很容易地做到这一点。

在 Vim 中打开该文件,然后输入:

:% normal 019l6r0<Enter>



:% normal表示对文件的每一行执行下一个命令。

0意思为:将光标移到行首。

19l意思是:将光标向右移动19次

6r0意思是:用 0 替换接下来的 6 个字符


我知道这些命令乍一看可能有点晦涩难懂。但你只需要学习几个非常简单的命令就可以完成你需要做的事情。

0将光标移动到行首
$将光标移动到行尾

h将光标向左移动
j将光标向下移动
k将光标向上移动
l将光标向右移动

r将光标下的字符替换为下一个按下的字符

在任何命令前输入一个数字,则该命令将执行“number”次。

:% normal <list of commands><Enter>在文件的每一行上列出命令列表


您还可以记录一系列编辑,然后在文件的每一行上重播相同的编辑。

记录命令。

qa<commands>q

然后,对文件的每一行重播命令。

:% normal @a<Enter>

相关内容