批处理+VBS脚本实现纯文本代码格式化输出
2011年06月06日
鉴于一次无聊时将日志里面的代码全部格式化成跟编译器里面相同格式后,发现这样的日志看起来顺眼多了,以后发日志便强迫性的要做相应更改,但是对于选定关键字->更改字体颜色代码这样的工作模式,在任何一个页面文字编译工具下都显得费时费力,这种情况下势必选择一种相应较快的方式来完成这项工作,使用Dreaweaver能比较快速的对选择文字进行字体编码,但是它不支持多选,那我想到了另一种方式来处理该情况:使用Office来进行文字颜色设置,由于它能进行多项不连续文字选择,因此会对代码的格式化工作提升很大效率,这种情况在代码量及整个日志内容较少的时候非常适用,能够快速地格式化出希望的代码样式来,但当我试着对一篇一两千字的日志进行处理的时候就发现问题了:日志内容超过XXXX字节!不对啊,我的日志怎么着也不会写超过5、6K啊,切换HTML代码一看,原来由WORD转换的文字格式多了很多类似于的代码,并且自建了大量的CSS样式,基本上对于每一个词或句都进行了一次代码处理,导致很多重复做功与无用功!
要在一个长达5、6K的文本文件里面去查找/替换无用的HTML标签,难度可想而知,我可不想写一篇日志只用几分钟,修改格式就要用到一两天的时间!其实对代码进行格式化的处理很简单,就设一个代码区背景色,替换一下空格为html标记,分别替换各部分不同功能代码为不同颜色即可,只做到对这几个关键部分的颜色替换,根本用不着那么多无用的HTML冗余信息,既然OFFICE不好用,那么自己来写一个小工具转换代码格式吧!
思路:由于现在的网络文字编译器都支持带HTML格式的复制,因此我们直接将所需转换的代码存为html文件,然后再用脚本进行替换处理以使其达到我们所需的HTML格式。
如下方代码:
/***********************************************************
* 函数名 : MsgBoxEx
* 参 数 :
* hwnd, szText, szCaption, uType
* 返回值 : int
* 功 能 : 在创建MessageBox之前, 创建CBT钩子与Keyboard钩子
* 用以转发捕获的按键消息
* 创 建 : KOUKON [2011/04/21]
* 备 注 :
**********************************************************/
int MsgBoxEx(HWND hwnd, TCHAR *szText, TCHAR *szCaption, UINT uType)
{
int ret;
g_hMsgCBTHook = SetWindowsHookEx(
WH_CBT,
CBTProc,
NULL,
GetCurrentThreadId()
);
g_hMsgKbdHook = SetWindowsHookEx(
WH_KEYBOARD,
KeyBordProc,
NULL,
GetCurrentThreadId()
);
ret = MessageBox(hwnd, szText, szCaption, uType);
return ret;
}
直接将纯文本存到html里面,将里面的tab标签全部转换成空格以便作进一步处理。
第二步即将里面的回车换行、空格及段落标签与注释的颜色信息标出,由于此类操作只需要做一次即可,所以我们用正则表达式判断是否已作相应处理。
到此为准备工作,当这一切准备完善之后就需要正式对我们的关键字进行处理了,我们将三个参数传到VBS脚本,所需要做格式处理的文件名、需要处理的关键字、关键字所标注的颜色(如:注释008000 类型名0000ff 函数名880000 变量名000080 常量及宏名A000A0),然后对文件中的相应文字添加颜色标签,此处要注意,所查找的关键字应避开多行注释与单行注释里面的内容,因为这两处地方统一着色为注释文本颜色。
最后将替换后的文本写回到指定的文件里面,即完成一个关键字的处理。
以上即为一次关键字替换工作,要作批量处理,我们即可建一批处理文件来批量调用关键字,这里我用一个文本文件来存储格式化的颜色与关键字template.txt,内容大致如下:
0000ff
long
int
if
else
switch
UINT
TCHAR
BOOL
第一行为关键字颜色,从第三行起为各关键字,一个关键字占位一行。调用批处理代码如下fmtCode.bat:
@echo off
setlocal enabledelayedexpansion
title fmtCode.::.By 呼吸新世界
set "strColor="
set "strKey="
set /a offset=0
for /f "tokens=*" %%i in ('more +!offset! template.txt') do (
REM echo.%%i
set "strColor=%%i"
goto :_getKey
)
:_getKey
set /a offset=!offset!+2
for /f "tokens=*" %%i in ('more +!offset! template.txt') do (
REM echo.%%i
set "strKey=%%i !strKey!"
)
echo strColor is : !strColor!
echo strKey is: !strKey!
echo.&echo.
for %%i in (!strKey!) do (
cscript //nologo fmtcode.vbs test.htm %%i !strColor!
)
pause
goto :EOF
文本替换脚本如下fmtCode.vbs:
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'ScriptName : fmtCode
'Description: 设置指定关键字代码为指定颜色,并写入成html格式
'Author : 呼吸新世界 [2011/06/06]
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Dim wsh, fso, fil, reg, matchCollection, regTmp
Dim strFileName, strContent, strKeyword, strColor
Sub Init()
If (WScript.Arguments.Count " & Chr(13)+Chr(10) & strContent & Chr(13)+Chr(10) & ""
WScript.Echo "段落标记添加完毕……"
End If
'注释行添色添加
If InStr(strContent, "") " & Chr(13)+Chr(10) & match.Value & "" & Chr(13)+Chr(10))
Next
End If
reg.Pattern = "(.*)(//.*)"
If reg.Test(strContent) Then
WScript.Echo "单行注释匹配成功……"
Set matchCollection = reg.Execute(strContent)
For Each match In matchCollection
WScript.Echo match.Value
strContent = Replace(strContent, match.Value, match.Submatches.Item(0) & "" & match.Submatches.Item(1) & "")
Next
End If
WScript.Echo "注释行颜色添加完毕……"
End If
End Sub
Sub ReContent()
'查找符合条件的行
reg.Pattern = "(.*?\b)(" & strKeyword & "\b)(.*)"
WScript.Echo reg.Pattern & " " & reg.Test(strContent)
Set matchCollection = reg.Execute(strContent)
For Each match In matchCollection
regTmp.Pattern = "(\* |//)" '注释行不算
WScript.Echo "Current matches count: " & CStr(match.Submatches.Count)
If Not regTmp.Test(match.Submatches.Item(0)) Then
'创建临时正则式
Set reg1 = New RegExp
reg1.Pattern = reg.Pattern
Set matchCol1 = reg1.Execute(match.Value)
'遍历子式
Do While matchCol1.Count > 0
For Each match1 In matchCol1
'判断是否代码后面注释
regTmp.Pattern = "//"
If Not regTmp.Test(match1.Submatches.Item(0)) Then
WScript.Echo match1.Submatches.Item(0) & "【" & match1.Submatches.Item(1) & "】" & match1.Submatches.Item(2)
strContent = Replace(strContent, match1.Value, match1.Submatches.Item(0) & "" & match1.Submatches.Item(1) & "" & match1.Submatches.Item(2))
Set matchCol1 = reg1.Execute(match1.Submatches.Item(2))
Exit For
Else
Exit Do
End If
Next
Loop
End If
Next
End Sub
Sub Destroy()
Set fil = fso.OpenTextFile(strFileName, ForWriting, True)
fil.Write strContent
fil.Close
Set regTmp = Nothing
Set reg = Nothing
Set fil = Nothing
Set fso = Nothing
End Sub
Call Init()
Call ReContent()
Call Destroy()
这是处理后的最终结果:
/***********************************************************
* 函数名 : MsgBoxEx
* 参 数 :
* hwnd, szText, szCaption, uType
* 返回值 : int
* 功 能 : 在创建MessageBox之前, 创建CBT钩子与Keyboard钩子
* 用以转发捕获的按键消息
* 创 建 : KOUKON [2011/04/21]
* 备 注 :
**********************************************************/
int MsgBoxEx(HWND hwnd, TCHAR *szText, TCHAR *szCaption, UINT uType)
{
int ret;
g_hMsgCBTHook = SetWindowsHookEx(
WH_CBT,
CBTProc,
NULL,
GetCurrentThreadId()
);
g_hMsgKbdHook = SetWindowsHookEx(
WH_KEYBOARD,
KeyBordProc,
NULL,
GetCurrentThreadId()
);
ret = MessageBox(hwnd, szText, szCaption, uType);
return ret;
}
2011年06月06日
鉴于一次无聊时将日志里面的代码全部格式化成跟编译器里面相同格式后,发现这样的日志看起来顺眼多了,以后发日志便强迫性的要做相应更改,但是对于选定关键字->更改字体颜色代码这样的工作模式,在任何一个页面文字编译工具下都显得费时费力,这种情况下势必选择一种相应较快的方式来完成这项工作,使用Dreaweaver能比较快速的对选择文字进行字体编码,但是它不支持多选,那我想到了另一种方式来处理该情况:使用Office来进行文字颜色设置,由于它能进行多项不连续文字选择,因此会对代码的格式化工作提升很大效率,这种情况在代码量及整个日志内容较少的时候非常适用,能够快速地格式化出希望的代码样式来,但当我试着对一篇一两千字的日志进行处理的时候就发现问题了:日志内容超过XXXX字节!不对啊,我的日志怎么着也不会写超过5、6K啊,切换HTML代码一看,原来由WORD转换的文字格式多了很多类似于的代码,并且自建了大量的CSS样式,基本上对于每一个词或句都进行了一次代码处理,导致很多重复做功与无用功!
要在一个长达5、6K的文本文件里面去查找/替换无用的HTML标签,难度可想而知,我可不想写一篇日志只用几分钟,修改格式就要用到一两天的时间!其实对代码进行格式化的处理很简单,就设一个代码区背景色,替换一下空格为html标记,分别替换各部分不同功能代码为不同颜色即可,只做到对这几个关键部分的颜色替换,根本用不着那么多无用的HTML冗余信息,既然OFFICE不好用,那么自己来写一个小工具转换代码格式吧!
思路:由于现在的网络文字编译器都支持带HTML格式的复制,因此我们直接将所需转换的代码存为html文件,然后再用脚本进行替换处理以使其达到我们所需的HTML格式。
如下方代码:
/***********************************************************
* 函数名 : MsgBoxEx
* 参 数 :
* hwnd, szText, szCaption, uType
* 返回值 : int
* 功 能 : 在创建MessageBox之前, 创建CBT钩子与Keyboard钩子
* 用以转发捕获的按键消息
* 创 建 : KOUKON [2011/04/21]
* 备 注 :
**********************************************************/
int MsgBoxEx(HWND hwnd, TCHAR *szText, TCHAR *szCaption, UINT uType)
{
int ret;
g_hMsgCBTHook = SetWindowsHookEx(
WH_CBT,
CBTProc,
NULL,
GetCurrentThreadId()
);
g_hMsgKbdHook = SetWindowsHookEx(
WH_KEYBOARD,
KeyBordProc,
NULL,
GetCurrentThreadId()
);
ret = MessageBox(hwnd, szText, szCaption, uType);
return ret;
}
直接将纯文本存到html里面,将里面的tab标签全部转换成空格以便作进一步处理。
第二步即将里面的回车换行、空格及段落标签与注释的颜色信息标出,由于此类操作只需要做一次即可,所以我们用正则表达式判断是否已作相应处理。
到此为准备工作,当这一切准备完善之后就需要正式对我们的关键字进行处理了,我们将三个参数传到VBS脚本,所需要做格式处理的文件名、需要处理的关键字、关键字所标注的颜色(如:注释008000 类型名0000ff 函数名880000 变量名000080 常量及宏名A000A0),然后对文件中的相应文字添加颜色标签,此处要注意,所查找的关键字应避开多行注释与单行注释里面的内容,因为这两处地方统一着色为注释文本颜色。
最后将替换后的文本写回到指定的文件里面,即完成一个关键字的处理。
以上即为一次关键字替换工作,要作批量处理,我们即可建一批处理文件来批量调用关键字,这里我用一个文本文件来存储格式化的颜色与关键字template.txt,内容大致如下:
0000ff
long
int
if
else
switch
UINT
TCHAR
BOOL
第一行为关键字颜色,从第三行起为各关键字,一个关键字占位一行。调用批处理代码如下fmtCode.bat:
@echo off
setlocal enabledelayedexpansion
title fmtCode.::.By 呼吸新世界
set "strColor="
set "strKey="
set /a offset=0
for /f "tokens=*" %%i in ('more +!offset! template.txt') do (
REM echo.%%i
set "strColor=%%i"
goto :_getKey
)
:_getKey
set /a offset=!offset!+2
for /f "tokens=*" %%i in ('more +!offset! template.txt') do (
REM echo.%%i
set "strKey=%%i !strKey!"
)
echo strColor is : !strColor!
echo strKey is: !strKey!
echo.&echo.
for %%i in (!strKey!) do (
cscript //nologo fmtcode.vbs test.htm %%i !strColor!
)
pause
goto :EOF
文本替换脚本如下fmtCode.vbs:
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'ScriptName : fmtCode
'Description: 设置指定关键字代码为指定颜色,并写入成html格式
'Author : 呼吸新世界 [2011/06/06]
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Dim wsh, fso, fil, reg, matchCollection, regTmp
Dim strFileName, strContent, strKeyword, strColor
Sub Init()
If (WScript.Arguments.Count " & Chr(13)+Chr(10) & strContent & Chr(13)+Chr(10) & ""
WScript.Echo "段落标记添加完毕……"
End If
'注释行添色添加
If InStr(strContent, "") " & Chr(13)+Chr(10) & match.Value & "" & Chr(13)+Chr(10))
Next
End If
reg.Pattern = "(.*)(//.*)"
If reg.Test(strContent) Then
WScript.Echo "单行注释匹配成功……"
Set matchCollection = reg.Execute(strContent)
For Each match In matchCollection
WScript.Echo match.Value
strContent = Replace(strContent, match.Value, match.Submatches.Item(0) & "" & match.Submatches.Item(1) & "")
Next
End If
WScript.Echo "注释行颜色添加完毕……"
End If
End Sub
Sub ReContent()
'查找符合条件的行
reg.Pattern = "(.*?\b)(" & strKeyword & "\b)(.*)"
WScript.Echo reg.Pattern & " " & reg.Test(strContent)
Set matchCollection = reg.Execute(strContent)
For Each match In matchCollection
regTmp.Pattern = "(\* |//)" '注释行不算
WScript.Echo "Current matches count: " & CStr(match.Submatches.Count)
If Not regTmp.Test(match.Submatches.Item(0)) Then
'创建临时正则式
Set reg1 = New RegExp
reg1.Pattern = reg.Pattern
Set matchCol1 = reg1.Execute(match.Value)
'遍历子式
Do While matchCol1.Count > 0
For Each match1 In matchCol1
'判断是否代码后面注释
regTmp.Pattern = "//"
If Not regTmp.Test(match1.Submatches.Item(0)) Then
WScript.Echo match1.Submatches.Item(0) & "【" & match1.Submatches.Item(1) & "】" & match1.Submatches.Item(2)
strContent = Replace(strContent, match1.Value, match1.Submatches.Item(0) & "" & match1.Submatches.Item(1) & "" & match1.Submatches.Item(2))
Set matchCol1 = reg1.Execute(match1.Submatches.Item(2))
Exit For
Else
Exit Do
End If
Next
Loop
End If
Next
End Sub
Sub Destroy()
Set fil = fso.OpenTextFile(strFileName, ForWriting, True)
fil.Write strContent
fil.Close
Set regTmp = Nothing
Set reg = Nothing
Set fil = Nothing
Set fso = Nothing
End Sub
Call Init()
Call ReContent()
Call Destroy()
这是处理后的最终结果:
/***********************************************************
* 函数名 : MsgBoxEx
* 参 数 :
* hwnd, szText, szCaption, uType
* 返回值 : int
* 功 能 : 在创建MessageBox之前, 创建CBT钩子与Keyboard钩子
* 用以转发捕获的按键消息
* 创 建 : KOUKON [2011/04/21]
* 备 注 :
**********************************************************/
int MsgBoxEx(HWND hwnd, TCHAR *szText, TCHAR *szCaption, UINT uType)
{
int ret;
g_hMsgCBTHook = SetWindowsHookEx(
WH_CBT,
CBTProc,
NULL,
GetCurrentThreadId()
);
g_hMsgKbdHook = SetWindowsHookEx(
WH_KEYBOARD,
KeyBordProc,
NULL,
GetCurrentThreadId()
);
ret = MessageBox(hwnd, szText, szCaption, uType);
return ret;
}