中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [原创]自己写了一个简单的文字替换脚本(vbs)
作者:
标题: [原创]自己写了一个简单的文字替换脚本(vbs) 上一主题 | 下一主题
sonicandy
中级用户





积分 273
发帖 91
注册 2007-5-7
状态 离线
『楼 主』:  [原创]自己写了一个简单的文字替换脚本(vbs) 使用 LLM 解释/回答一下

各位高手,小弟献丑了。
还有许多不足之处请多多指教。
Option Explicit 
'声明全局变量/对象
Dim ie,wnd,id,curpath,fso,dlg,ext,reg,filelist
Dim matchcase,fcount,shell,shellapp,delims
Const ForReading = 1, ForWriting = 2

Set shell = CreateObject("wscript.shell")
Set fso = CreateObject("scripting.FileSystemObject")
Set dlg = CreateObject("UserAccounts.CommonDialog")
Set shellapp = CreateObject("shell.application")
Set reg = new regexp

reg.global = True
curpath = fso.GetFolder(shell.currentdirectory).shortpath

configure
While True
wscript.sleep 1000
Wend

'配置脚本任务
Sub Configure
Set ie = wscript.CreateObject("InternetExplorer.Application","ie_")
'设置ie对象
ie.Navigate curpath & "\replace.htm"
ie.ToolBar = 0
ie.StatusBar = 0
ie.Width = 684
ie.Height = 259
ie.left=fix((ie.document.parentwindow.screen.availwidth-ie.width)/2) '水平居中'
ie.top=fix((ie.document.parentwindow.screen.availheight-ie.height)/2) '垂直居中'
ie.Resizable = False
ie.Visible = True
Set wnd = ie.document.parentwindow
Set id = ie.document.all

'设置ie窗口事件处理函数
id.addfolder.onclick = getref("addfolder")
id.addfile.onclick = getref("addfile")
id.savelist.onclick = getref("savelist")
id.loadlist.onclick = getref("loadlist")
id.reg1.onchange = getref("reg1_change")
id.reg2.onchange = getref("reg2_change")
id.startsearch.onclick = getref("startsearch")
id.startreplace.onclick = getref("startreplace")
id.help.onclick = getref("help")
id.about.onclick = getref("about")
End Sub

'遍历所有选择的文件
Sub traverse(process)
Dim files,file,i,ret,str,old
If id.from.value="" Then
Call MsgBox("请输入搜索内容!",VbCritical)
Exit Sub
End If
If id.matchcase.checked Then
matchcase = 0
Else
matchcase = 1
End If
reg.ignorecase = Not id.matchcase.checked
reg.pattern = id.from.value
fcount = 0
files = Split(id.filelist.value,vbcrlf)
For i=0 To UBound(files)
If files(i)<>"" Then
Set file = fso.opentextfile(files(i),forreading)
'跳过空文件
If Not file.atendofstream Then
'str在调用process函数时可能会被修改
str = file.readall
old = str '用于分析完后的比较
'调用参数中指定的回调函数,并根据情况决定是否结束
ret = process(fso.getabsolutepathname(files(i)),str)
file.close

If str<>old Then
If ret=True Then
Set file = fso.opentextfile(files(i),forwriting)
file.write str
file.close
ElseIf MsgBox("是否保存当前文件?",vbyesno)=vbyes Then
Set file = fso.opentextfile(files(i),forwriting)
file.write str
file.close
End If
End If
If ret=False Then
Exit Sub
End If

End If
End If
Next
If fcount=0 Then
Call MsgBox("抱歉,无法找到字符串“"& id.from.value & "”!",VbExclamation)
Else
Call MsgBox("共找到 " & fcount & " 处结果,搜索完毕!",VbInformation)
End If
End Sub

'根据字符串和偏移量得到行值和坐标
Sub getposition(str,offset,length,x,y,line)
Dim linestart,lineend,delta
'得到行首位置
linestart = InstrRev(str,vbcrlf,offset)
delta = 2
If linestart=0 Then
linestart = InstrRev(str,vblf,offset)
delta = 1
End If
If linestart=0 Then
linestart = InstrRev(str,vbcr,offset)
delta = 1
End If
If linestart=0 And delta=-2 Then
linestart = 1
Else
linestart = linestart + delta
End If

'得到行尾位置
lineend = InStr(offset+length,str,vbcrlf)
If lineend=0 Then
lineend = InStr(offset,str,vblf)
End If
If lineend=0 Then
lineend = InStr(offset,str,vbcr)
End If
If lineend=0 Then
lineend=Len(str)
Else
lineend = lineend
End If
If lineend-linestart<=0 Then
lineend = linestart + 1
End If
'得到行值和坐标
line = Mid(str,linestart,lineend-linestart)
x = offset - linestart + 1
y = UBound(Split(Left(str,linestart),vblf)) + 1
End Sub

'单击按钮
Sub startsearch()
If id.regular.checked Then
Call traverse(getref("regularsearch"))
Else
Call traverse(getref("normalsearch"))
End If
End Sub

'正则搜索回调函数
Function regularsearch(file,str)
Dim matches,match,ret,x,y,line
If reg.test(str) Then
Set matches = reg.execute(str)
For Each match In matches
Call getposition(str,match.firstindex+1,match.length,x,y,line)
fcount = fcount + 1
ret = MsgBox("文件:" & file & vbcrlf & "位置:" & y & "行," & x & "列" & vbcrlf _
& "匹配:“" & match.value & "”" & vbcrlf & "行值:" & line,vbokcancel,"搜索")
If ret=vbcancel Then
regularsearch = False
Exit Function
End If
Next
End If
regularsearch = True
End Function

'一般搜索回调函数
Function normalsearch(file,str)
Dim offset,ret,line,x,y
offset = 1
While offset<>0
offset = InStr(offset,str,id.from.value,matchcase)
If offset<>0 Then
Call getposition(str,offset,Len(id.from.value),x,y,line)
If Not id.fullword.checked Or isfullword(str,offset) Then
fcount = fcount + 1
ret = MsgBox("文件:" & file & vbcrlf & "位置:" & y & "行," & x & "列" & vbcrlf _
& "匹配:“" & id.from.value & "”" & vbcrlf & "内容:" & line,vbokcancel,"搜索")
If ret=vbcancel Then
normalsearch = False
Exit Function
End If
End If
offset = offset + 1
End If
Wend
normalsearch = True
End Function

'单击按钮
Sub startreplace()
If id.regular.checked Then
Call traverse(getref("regularreplace"))
Else
Call traverse(getref("normalreplace"))
End If
End Sub

'正则替换回调函数
Function regularreplace(file,str)
Dim matches,match,ret,x,y,line,dest,i,submatch,delta
delta = 0 '改动后的偏移量
If reg.test(str) Then
Set matches = reg.execute(str)
For Each match In matches
Call getposition(str,match.firstindex+1+delta,match.length,x,y,line)
fcount = fcount + 1
'得到替换后的字符串
dest = id.To.value
dest = Replace(dest,"\t",vbtab)
dest = Replace(dest,"\n",vbcrlf)
dest = Replace(dest,"\0",match.value)
i = 1
For Each submatch In match.submatches
dest = Replace(dest,"\" & i,submatch)
i = i + 1
Next
'是否提示
If id.prompt.checked Then
ret = MsgBox("文件:" & file & vbcrlf & "位置:" & y & "行," & x & "列" & delta & "," & match.firstindex & vbcrlf _
& "行值:" & line & vbcrlf & "匹配:“" & match.value & "”" & vbcrlf _
& "替换:“" & dest & "”",vbyesnocancel,"替换")
Else
ret = vbyes
End If
'更改字符串
If ret=vbyes Then
str = Left(str,match.firstindex+delta) & dest & Mid(str,match.firstindex+1+match.length+delta)
delta = delta + Len(dest) - match.length
End If
If ret=vbcancel Then
regularreplace = False
Exit Function
End If
Next
End If
regularreplace = True
End Function

'判断是否为整词
Function isfullword(str,offset)
reg.pattern = "" '不是汉字字母数字
'不是文件中的第一个字符,并且前一个字符不是汉字,字母,数字
If offset>1 Then
If Not reg.test(Mid(str,offset-1,1)) Then
isfullword = False
Exit Function
End If
End If
'不是文件中的最后一个字符,并且后一个字符不是汉字,字母,数字
If offset+Len(id.from.value)<=Len(str) Then
If Not reg.test(Mid(str,offset+Len(id.from.value),1)) Then
isfullword = False
Exit Function
End If
End If
isfullword = True
End Function

'一般替换回调函数
Function normalreplace(file,str)
Dim offset,ret,line,x,y
offset = 1
While offset<>0
offset = InStr(offset,str,id.from.value,matchcase)
If offset<>0 Then
Call getposition(str,offset,Len(id.from.value),x,y,line)
If Not id.fullword.checked Or isfullword(str,offset) Then
fcount = fcount + 1
'是否提示
If id.prompt.checked Then
ret = MsgBox("文件:" & file & vbcrlf & "位置:" & y & "行," & x & "列" & vbcrlf _
& "行值:" & line & vbcrlf & "匹配:“" & id.from.value & "”" & vbcrlf _
& "替换:“" & id.To.value & "”",vbyesnocancel,"替换")
Else
ret = vbyes
End If
'更改字符串
If ret=vbyes Then
str = Left(str,offset-1) & id.To.value & Mid(str,offset+Len(id.from.value))
End If
If ret=vbcancel Then
normalreplace = False
Exit Function
End If
End If
offset = offset + Len(id.To.value)
End If
Wend
normalreplace = True
End Function

'选择搜索的字符串中的内容
Sub reg1_change()
id.from.value = id.from.value & id.reg1.value
Call id.from.focus()
id.reg1.value = "正则表达式"
id.regular.checked = True
End Sub

'选择替换为字符串中的内容
Sub reg2_change()
id.to.value = id.To.value & id.reg2.value
Call id.to.focus()
id.reg2.value = "正则表达式"
id.regular.checked = True
End Sub

'单击
Sub addfolder()
If InStr(id.ext.value,";")=0 Then
MsgBox "请至少输入一个分号!",vbcritical
Exit Sub
End If
If Right(id.ext.value,1)<>";" Then
MsgBox "请在扩展名末尾添加分号!",vbcritical
Exit Sub
End If
Dim temp,folder
temp = showSelFolderDlg
If temp="" Then Exit Sub
Set folder = fso.getfolder(temp)
ext = Split(id.ext.value,";")
Call getfilesinfolder(folder)
End Sub

'获得指定目录下的文件,并根据决定是否递归
Sub getfilesinfolder(folder)
Dim i,file,subfolder
For Each file In folder.files
For i=0 To UBound(ext)-1
If ext(0)="*" Or fso.getextensionname(file.path)=ext(i) Then
id.filelist.value = id.filelist.value & file.shortpath & vbcrlf
Exit For
End If
Next
Next
If id.subfolder.checked Then
For Each subfolder In folder.subfolders
Call getfilesinfolder(subfolder)
Next
End If
End Sub

'单击
Sub addfile()
id.filelist.value = id.filelist.value & showSelFilesDlg
End Sub

'显示选择目录对话框
Function showSelFolderDlg()
Dim folder,folderitem
Set folder = shellapp.browseforfolder(0,"选择目标文件夹",0)
If Not folder Is Nothing Then
Set folderitem = folder.items.item
showSelFolderDlg = folderitem.path
End If
End Function

'显示选择多文件对话框
Function showSelFilesDlg()
Dim intResult,i,temp
dlg.Filter = "所有文件|*.*"
dlg.Flags = &H0200
intResult = dlg.ShowOpen
If intResult <> 0 Then
temp = Split(dlg.FileName," ")
If UBound(temp) = 0 Then
showSelFilesDlg = temp(0) & vbcrlf
Else
showSelFilesDlg = ""
For i=1 To UBound(temp)
showSelFilesDlg = showSelFilesDlg & temp(0) & temp(i) & vbcrlf
Next
End If
End If
End Function

'单击
Sub savelist()
Dim name,file
name = showSelFileDlg()
If name = "" Then Exit Sub
Set file = fso.opentextfile(name,forwriting,true)
file.write id.filelist.value
file.close
End Sub

'单击
Sub loadlist()
Dim name,file
name = showSelFileDlg()
If name = "" Then Exit Sub
Set file = fso.opentextfile(name,forreading,false)
id.filelist.value = file.readall
file.close
End Sub

'显示选择单个文件对话框
Function showSelFileDlg()
dlg.Filter = "所有文件|*.*"
dlg.Flags = &H0000

If dlg.ShowOpen() <> 0 Then
showSelFileDlg = dlg.FileName
Else
showSelFileDlg = ""
End If
End Function

'处理ie进程的退出事件
Sub ie_onquit
Set dlg = Nothing
Set shell = Nothing
Set fso = Nothing
Set shellapp = Nothing
Set reg = Nothing
wscript.disconnectobject ie
Set ie = Nothing
Call wscript.quit()
End Sub

'单击
Sub help()
Call shell.run(curpath & "\help.chm")
End Sub

'单击
Sub about()
Call MsgBox("感谢您使用《字符串替换脚本v0.1》" & vbcrlf _
& "如果您有什么建议或者问题可以联系" & vbcrlf _
& "sonic_andy ",vbinformation,"关于")
End Sub


Last edited by sonicandy on 2007-10-8 at 06:54 PM ]


   此帖被 +28 点积分       点击查看详情   
评分人:【 bjsh 分数: +16  时间:2007-5-8 22:16
评分人:【 baomaboy 分数: +8  时间:2007-5-8 23:54
评分人:【 huzixuan 分数: +4  时间:2007-5-9 12:51


附件 1: 字符串替换脚本.JPG (2007-5-8 21:54, 33.94 KiB,下载次数: 11)


附件 2: replace.zip (2007-5-8 21:54, 39.48 KiB,下载次数: 106)
2007-5-8 21:54
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
utem999
初级用户




积分 135
发帖 54
注册 2006-9-10
状态 离线
『第 2 楼』:   使用 LLM 解释/回答一下

创意
真是有创意呀




992912
2007-5-9 08:49
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
ccwan
金牌会员




积分 2725
发帖 1160
注册 2006-9-23
来自 河北廊坊
状态 离线
『第 3 楼』:   使用 LLM 解释/回答一下

好长的代码!写的不错,收藏了。




三人行,必有吾师焉。 学然后知不足,教然后知困,然后能自强也。
2007-5-9 09:26
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
vus520
初级用户





积分 34
发帖 15
注册 2007-6-12
状态 离线
『第 4 楼』:   使用 LLM 解释/回答一下

不能运行中,第九行的UserAccounts.CommonDialog不能创建~~


2007-9-6 02:31
查看资料  发送邮件  发短消息  网志  OICQ (254908116)  编辑帖子  回复  引用回复
voiL
中级用户





积分 384
发帖 189
注册 2005-10-19
状态 离线
『第 5 楼』:   使用 LLM 解释/回答一下

方便又实在呵呵...


2007-9-6 02:42
查看资料  发短消息  网志   编辑帖子  回复  引用回复
qq43142691
中级用户





积分 327
发帖 152
注册 2007-5-4
状态 离线
『第 6 楼』:   使用 LLM 解释/回答一下

运行出错。


2007-9-6 02:45
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
sonicandy
中级用户





积分 273
发帖 91
注册 2007-5-7
状态 离线
『第 7 楼』:   使用 LLM 解释/回答一下

需要下载附件.


2007-9-6 20:54
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
vus520
初级用户





积分 34
发帖 15
注册 2007-6-12
状态 离线
『第 8 楼』:   使用 LLM 解释/回答一下

第九行的UserAccounts.CommonDialog不能创建~~

附件也不能运行


2007-9-7 09:24
查看资料  发送邮件  发短消息  网志  OICQ (254908116)  编辑帖子  回复  引用回复
sonicandy
中级用户





积分 273
发帖 91
注册 2007-5-7
状态 离线
『第 9 楼』:   使用 LLM 解释/回答一下

如果您使用的是 Windows 2000,我们不知道实现此操作的方法,至少操作系统中没有内置这样的方法。但如果您使用的是 Windows XP,情况就不同了。在 Windows XP 上,您可以使用“UserAccounts.CommonDialog”对象向用户显示一个标准的“文件打开”对话框。


摘自
嗨,Scripting Guy! 我如何向用户显示一个用来选择文件的对话框?
http://www.microsoft.com/china/technet/community/scriptcenter/resources/hey0128.mspx

Last edited by sonicandy on 2007-9-8 at 09:43 AM ]


2007-9-8 09:38
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
mountvol
初级用户





积分 186
发帖 117
注册 2006-8-14
状态 离线
『第 10 楼』:   使用 LLM 解释/回答一下

375行:
showSelFilesDlg = temp(0) & ";"
如果单个文件就会因为文件名后面多了个;而导致打开文件错误。
另外读取文件后再打开单个文件由于没有清空内容,会导致打开文件失败。
还有增加目录也会失败。


2007-9-8 12:48
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
sonicandy
中级用户





积分 273
发帖 91
注册 2007-5-7
状态 离线
『第 11 楼』:   使用 LLM 解释/回答一下

mountvol朋友,多谢你热心的提出这个脚本的缺陷:

375行:
showSelFilesDlg = temp(0) & ";"
如果单个文件就会因为文件名后面多了个;而导致打开文件错误。

这个问题已经修改,修改方式:把";"替换为vbcrlf

另外读取文件后再打开单个文件由于没有清空内容,会导致打开文件失败。
还有增加目录也会失败。

这个问题我按你说的操作了一下,没有发现错误:
1 选择包含子目录
2 点击添加目录,选择我的文档
3 将读出的所有txt文件列表保存为一个文件list
4 清空文件列表中的内容
5 读入刚才保存的文件列表
6 打开文件
7 增加目录
8 进行搜索操作
请说明一下以上的操作步骤是否有偏差.

Last edited by sonicandy on 2007-9-8 at 09:28 PM ]


2007-9-8 21:24
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
wydos
中级用户





积分 304
发帖 117
注册 2006-4-4
状态 离线
『第 12 楼』:   使用 LLM 解释/回答一下

收藏了,最近在学习vbscript


2007-10-21 20:45
查看资料  发送邮件  发短消息  网志  OICQ (327337973)  编辑帖子  回复  引用回复
xiaoyao1987
初级用户





积分 63
发帖 24
注册 2006-12-19
来自 南京
状态 离线
『第 13 楼』:   使用 LLM 解释/回答一下

OK了。。。

Last edited by xiaoyao1987 on 2007-10-22 at 10:07 AM ]


2007-10-22 10:00
查看资料  访问主页  发短消息  网志  OICQ (352120473)  编辑帖子  回复  引用回复
kill
新手上路





积分 10
发帖 3
注册 2007-8-2
来自 广东省
状态 离线
『第 14 楼』:   使用 LLM 解释/回答一下

根本不行~~~~~~~~~~


2007-10-22 20:39
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: