我怎样才能在某些列位置进行替换?
例如:我想用 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>