编辑器:010Editor、ultraedit

1、010editor

官网下载:https://www.sweetscape.com/download/
汉化:https://www.52pojie.cn/thread-1863194-1-1.html
宇宙最强 010 Editor 模板开发教程(附带示例):https://bbs.pediy.com/thread-257797.htm

010editor 是一款十六进制编辑器,和 winhex 相比支持更灵活的脚本语法,可以对文件、内存、磁盘进行操作,是二进制分析中十分强力的工具,能够解析多种文件格式并以友好的界面呈现。其强大的内部引擎使得任何人都可以定制所需的解析脚本或解析模板。

  • 二进制文件是一种计算机可读但人类不可读的文件(如果在文本编辑器中打开,二进制文件将显示为乱码)。
  • 十六进制编辑器是一个程序,它允许您查看和编辑二进制文件的单个字节。010 Editor 就是一个高级的十六进制编辑器,允许您编辑硬盘驱动器、软盘驱动器、内存密钥、闪存驱动器、CD-ROM、进程等中的字节。

010 Editor 一部分有点:

  • 查看并编辑任何二进制文件和文本文件,包括 Unicode 文件、C/C++、XML、PHP,等。
  • 独特的二进制模板技术允许你了解任何二进制文件格式。
  • 查找并修复硬盘驱动器、软驱、内存密钥、闪存驱动器、CD-ROM、进程等的问题。
  • 查找、替换、在多文件中查找、在多文件中替换、二进制比较、校验和/散列算法、直方图等,来分析和编辑文本和二进制数据。
  • 强大的 "模板、脚本" 功能。脚本引擎允许多任务的自动化(语言非常类似于 C)。
  • 以不同的格式导入和导出二进制数据。

在 010 的官网上已经有仓库存放​了大量的 "脚本、模板"  库可以使用

模板 功能

菜单 ---> Templates ---> Template Repository,会出现各种文件格式的模板。

比如选择 EXE 文件的模板来分析 PE 文件,然后打开一个 PE 文件,效果如图:

文件模板  

(*.bt) 用于识别文件类型 http://www.sweetscape.com/010editor/repository/templates/

  • 支持cab gzip rar zip cda midi mp3 ogg wav avi flv mp4 rm pdf iso vhd lnk dmp dex androidmanifest class
  • Drive.bt 解析mbr fat16 fat43 hfs ntfs等
  • elf.bt 解析Linux elf格式的文件
  • exe.bt 解析windows pe x86/x64 格式文件(dll sys exe ...)
  • macho.bt 解析mac os可执行文件
  • registrayhive.bt 解析注册表(Hive)文件
  • bson.bt 解析二进制json

脚本模板

常用的脚本库(*.1sc)用于操作数据http://www.sweetscape.com/010editor/repository/scripts/

  • CountBlocks.1sc 查找指定数据块
  • DecodeBase64.1sc 解码base64
  • EncodeBase64.1sc 编码base64
  • Entropy.1sc 计算熵
  • JoinFIle.1sc SplitFile.1sc 分隔合并文件
  • Js-unicode-escape.1sc Js-unicode-unescape.1sc URLDecoder.1sc js编码解码
  • CopyAsAsm.1sc CopyAsBinary.1sc CopyAsCpp.1sc CopyAsPython.1sc 复制到剪贴板
  • DumpStrings.1sc 查找所有ascii unicode字符串


 

模板的开发

010Editor脚本语法入门:https://www.jianshu.com/p/ba60ebd8f916

在 010 的官网上已经有仓库存放了大量的 脚本 和 模板 库供大伙使用。但问题一定是解决不完的,当遇到冷门文件而官方仓库没有模板咋办?办法只有一个:自己写。

010 模板(010 Editor Templates)的基本语法和 C 语言类似,毫不夸张的说你要是会 C 的话,你已经学会了一半。剩下一半你就记住这句话:将整个文件的二进制数据当作输入,将其强制转换为一个结构体就行了。不过当你动手开始实践的时候,你会发现事情果然没有那么简单的,要将整个文件的数据转换成一个结构体,其内部需要更细粒度的结构体来支撑。

前面说了一堆废话,还是要讲讲基本语法的,毕竟这是一篇从入门到踩坑系列教程。

变量类型

C 语言中基本变量类型都是支持,包括 int、char、short、long、float 等,结构体 struct,枚举 enum,位域 bitfield 以及联合体 union 也是没问题的。C 中常用的关键字 define、const 和 unsigned 等也是可以用在 010 模板中的。除此之外,Windows 中定义的变量类型也是受支持的,诸如 WORD、DWORD、UINT32、UINT64、LONG。

表达式及语法

C 中的各种加减乘除,大于小于,与或非等表达式也是可以用在模板中的,具体的如下:

  • 数值运算:+ - * / ~ ^ & | % ++ -- ?: << >> ()
  • 逻辑运算:&& || !
  • 比较操作:< ? <= >= == != !
  • 赋值操作:= += -= *= /= &= ^= %= |= <<= >>=

C 语言本身的语法并不复杂,在 010 模板中你更不必了解某些生僻的语法,只需要知道 if...else、while、for、switch 以及数组和函数即可。C 语言强大而复杂的指针在 010 中完全用不着,是不是贼开心,可以不用顶着多级指针去操作数据了。

需要注意的是在 010 模板中不能使用二维数组以及 goto 语句

特殊属性

在官网的文档中,给出了 010 模板中具有的特殊属性:

<format=hex|decimal|octal|binary,
    fgcolor=<color>,
    bgcolor=<color>,
    comment="<string>"|<function_name>,
    name="<string>"|<function_name>,
    open=true|false|suppress,
    hidden=true|false,
    read=<function_name>,
    write=<function_name>,
    size=<number>|<function_name>>

下面将简单介绍下这些属性

  • format: 以某种进制格式显示,默认为十进制,显示在 Vlaue 栏
  • fgcolor: 设置字体色
  • bgcolor: 设置背景色
  • comment: 添加注释,显示在 Comment 栏
  • name: 替换显示的字符,默认为结构体中的变量名,显示在 Name 栏
  • open: 设置树形图是否展开,默认不展开
  • hidden: 设置是否隐藏,默认为不隐藏
  • read: 读回调,返回字符串并显示在 Vlaue 栏
  • write: 写回调,将读回调返回的字符写入结构体某个字段中
  • size: 按需执行,可节约系统内存

把这些特殊属性归个类,不常用的属性有 openwrite 和 size,某些比较特殊情况下会用到的属性 name 和 hidden,花里胡哨时才会用到 fgcolor 和 bgcolor,快速开发模板你只需要记住 readformat 和 comment

上边提到特殊情况我展开说明下,name 属性我没怎么用到过,感觉是给强迫症用的,hidden 这个属性在某些情况下有奇效,比如定义的局部变量可能显示在结果中,这时候就可以利用<hidden=true>来隐藏冗余的输出。

下面我放两张图,帮助大伙更好的理解以上这几个特殊的属性,图 1 中的 1 处是 name 属性显示的字符,如果不指定 name 属性默认就是结构体中的变量名。2 处是 format 属性,默认是十进制,这里指定为 16 进制。3 处是背景颜色和字体颜色缩影,这里没设置颜色所以显示为空。4 处就是 comment 属性显示的位置。

pic01

背景颜色 bgcolor 和字体颜色 fgcolor 明眼人一看就明白了。

pic02

API 接口

010 模板的 Api 比较多,我将一些使用频率比较高的 Api 罗列出来,如果你想要完整的 Api 列表,请看​官网的函数接口(https://www.sweetscape.com/010editor/manual/FuncInterface.htm)。不过个人认为下面的 Api 已经足够使用了,除非你要写非常复杂的解析模板:

  • void BigEndian()
  • void LittleEndian()
  • char ReadByte(int64 pos=FTell())
  • uchar ReadUByte(int64 pos=FTell())
  • short ReadShort(int64 pos=FTell())
  • ushort ReadUShort(int64 pos=FTell())
  • int ReadInt(int64 pos=FTell())
  • uint ReadUInt(int64 pos=FTell())
  • int64 ReadInt64(int64 pos=FTell())
  • uint64 ReadUInt64(int64 pos=FTell())
  • void ReadBytes(uchar buffer[], int64 pos, int n)
  • char[] ReadString(int64 pos, int maxLen=-1)
  • int ReadStringLength(int64 pos, int maxLen=-1)
  • wstring ReadWString(int64 pos, int maxLen=-1)
  • int ReadWStringLength(int64 pos, int maxLen=-1)
  • void WriteByte(int64 pos, char value)
  • int FSeek(int64 pos)
  • int FSkip(int64 offset)
  • int64 FTell()
  • int FEof()
  • void Strcpy(char dest[], const char src[])
  • void Strcat(char dest[], const char src[])
  • int Strchr(const char s[], char c)
  • int Strcmp(const char s1[], const char s2[])
  • int Printf(const char format[] [, argument, ... ])
  • int SScanf(char str[], char format[], ...)
  • int SPrintf(char buffer[], const char format[] [, argument, ... ])

这些 Api 大部分都能猜出来是干嘛的,比如 ReadByte 是指定位置读取一个字节,WriteByte 是指定位置写入一个字节,Strcmp 是字符串比较,Printf 打印字符,SScanf 将字符数组 buffer 格式化为多种数据格式,SPrintf 将各种数据格式化后置于字符数组 buffer。

特别需要注意的是以下几个函数,对于解析偏移后的动态数据它们是不可或缺的:

  • FEof 判断当前读取位置是否在文件末尾
  • FTell 返回文件的当前读取位置
  • FSeek 将当前读取位置设置为指定地址
  • FSkip 将当前读取位置向前移动多个字节

如果你想要操控 010 模板内部指针的位置,你就得牢记模板在解析文件时内部指针的移动方式:

  • 每次在模板中定义变量时,读取位置都会向前移动该变量使用的字节数
  • ReadByte 等函数既可以读取数据也不会影响读取位置

示例:解析 .lib 文件

下面我就以微软的静态库.lib文件为例,给大伙演示一个 010 模板从无到有的完整过程。你想想如果你要解析某个文件,第一步会干嘛呢?当然是了解该文件的构成,所以第一步就是搜集相关的资料。

搜集资料

在看雪论坛上找到一篇LIB文件解析的文章,将其消化理解后我画了一张结构图来帮助大伙理解,如图:

要是没接触过 Lib 文件,是很难参悟上图的,所以我将上图简要的阐述下,可能会利于大伙理解:

  • 开头 8 字节固定为!<arch>.
  • 随后为 60 字节的第一链接成员以及 Size 字节的数据
  • 然后是第二链接成员及其数据
  • 紧接着又是长名称成员及其数据
  • 最后是每一个 Obj 成员及其数据

注意,Size 的具体值在其对应的成员结构体中指定。顺便再科普以下,Lib 文件其实是以特定格式打包多个 Obj 文件后的产物

定义结构

有了之前准备的那些资料,就可以为 010 模板定义核心的结构了,核心的结构如下所示:

#define IMAGE_ARCHIVE_START_SIZE 8
#define IMAGE_ARCHIVE_START "!<arch>\n"
#define IMAGE_ARCHIVE_LINKER_MEMBER "/               "
#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "//              "
 
typedef struct _ARCHIVE_START
{
    char StartStr[IMAGE_ARCHIVE_START_SIZE];
}ARCHIVE_START;
 
typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER {
    BYTE Name[16];
    BYTE Date[12];
    BYTE UserID[6];
    BYTE GroupID[6];
    BYTE Mode[8];
    BYTE Size[10];
    BYTE EndHeader[2];
}IMAGE_ARCHIVE_MEMBER_HEADER;
 
typedef struct _MEMBERDATA(ULONG Size)
{
    UCHAR Data[Size];
}MEMBERDATA;

一定要注意,IMAGE_ARCHIVE_MEMBER_HEADER 的 最后一个字段 EndHeader 必须是以 `\n 结尾,如果不是则必须将当前指针向后移动直到符合上述条件,否则后续的数据解析会连环出错。为了方便只需判断最后一个字节的 ascii 码是不是 10 即可,如果不是当前指针加 1 即可。

简单解析模板

俗话说饭要一口一口的吃,事要一点一点的做。所以先把 Obj 成员之外的简单结构解析了,这部分的代码如下:

#define IMAGE_ARCHIVE_START_SIZE 8
#define IMAGE_ARCHIVE_START "!<arch>\n"
#define IMAGE_ARCHIVE_LINKER_MEMBER "/               "
#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "//              "
 
typedef struct _ARCHIVE_START
{
    char StartStr[IMAGE_ARCHIVE_START_SIZE];
}ARCHIVE_START;
 
typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER {
    BYTE Name[16];
    BYTE Date[12];
    BYTE UserID[6];
    BYTE GroupID[6];
    BYTE Mode[8];
    BYTE Size[10];
    BYTE EndHeader[2];
}IMAGE_ARCHIVE_MEMBER_HEADER;
 
typedef struct _MEMBERDATA(ULONG Size)
{
    UCHAR Data[Size];
}MEMBERDATA;
 
//--------------------------------------
LittleEndian();
 
ARCHIVE_START Start;
 
IMAGE_ARCHIVE_MEMBER_HEADER FirstLinker;
if(ReadByte(FTell() + Atoi(FirstLinker.Size)) == 10)
{
    MEMBERDATA Data(Atoi(FirstLinker.Size) + 1);
}
else
{
    MEMBERDATA Data(Atoi(FirstLinker.Size));
}
 
IMAGE_ARCHIVE_MEMBER_HEADER SecondLinker;
if(ReadByte(FTell() + Atoi(SecondLinker.Size)) == 10)
{
    MEMBERDATA Data(Atoi(SecondLinker.Size) + 1);
}
else
{
    MEMBERDATA Data(Atoi(SecondLinker.Size));
}
 
IMAGE_ARCHIVE_MEMBER_HEADER LongNames;
if(ReadByte(FTell() + Atoi(LongNames.Size)) == 10)
{
    MEMBERDATA Data(Atoi(LongNames.Size) + 1);
}
else
{
    MEMBERDATA Data(Atoi(LongNames.Size));
}

010 模板语法是脚本类型的,即它也是顺序执行。代码的前半部分是一堆类型定义,所以执行的第一行代码是 LittleEndian(),该函数指定为小端解析。后半部分代码是把文件数据依次对应到某个变量,在解析时文件指针会跟随每个结构体的大小移动,解析的效果如图:

pic04

完整解析模板

前面已经解析了 Lib 文件中比较简单的结构,剩下的是多个 Obj 成员和数据,这部分解析起来比较复杂。而且最复杂的地方是将其文件名找到并显示在 Value 栏或者 Comment 栏中。所以必须使用 read 和 comment 回调来实现该功能,完整的模板代码如下:

#define IMAGE_ARCHIVE_START_SIZE 8
#define IMAGE_ARCHIVE_START "!<arch>\n"
#define IMAGE_ARCHIVE_LINKER_MEMBER "/               "
#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "//              "
 
typedef struct _ARCHIVE_START
{
    char StartStr[IMAGE_ARCHIVE_START_SIZE];
}ARCHIVE_START;
 
typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER {
    BYTE Name[16];
    BYTE Date[12];
    BYTE UserID[6];
    BYTE GroupID[6];
    BYTE Mode[8];
    BYTE Size[10];
    BYTE EndHeader[2];
}IMAGE_ARCHIVE_MEMBER_HEADER;
 
typedef struct _MEMBERDATA(ULONG Size)
{
    UCHAR Data[Size];
}MEMBERDATA;
 
typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER_OBJ(int i) {
    local int index <hidden=true>;
    index = i;
    BYTE Name[16];
    BYTE Date[12];
    BYTE UserID[6];
    BYTE GroupID[6];
    BYTE Mode[8];
    BYTE Size[10];
    BYTE EndHeader[2];
}IMAGE_ARCHIVE_MEMBER_HEADER_OBJ <comment=GetFullObjName,read=GetObjName>;
 
typedef struct _ALLOBJS
{
    local int i <hidden=true>;
    i = 0;
    while(!FEof())
    {
        IMAGE_ARCHIVE_MEMBER_HEADER_OBJ ObjMember(i++);
        if(FTell() + Atoi(ObjMember.Size) >= FileSize())
        {
            MEMBERDATA Data(Atoi(ObjMember.Size));
            break;
        }
 
        if(ReadByte(FTell() + Atoi(ObjMember.Size)) == 10)
        {
            MEMBERDATA Data(Atoi(ObjMember.Size) + 1);
        }
        else
        {
            MEMBERDATA Data(Atoi(ObjMember.Size));
        }
    }
}ALLOBJS;
 
string GetFullObjName(IMAGE_ARCHIVE_MEMBER_HEADER_OBJ& MemberHeader)
{
    local int j <hidden=true>;
    j = 0;
    local int NameOffset <hidden=true>;
    NameOffset = LongNameBase;
    while(j++ < MemberHeader.index)
    {
        NameOffset += Strlen(ReadString(NameOffset)) + 1;
    }
    return ReadString(NameOffset);
}
 
string GetObjName(IMAGE_ARCHIVE_MEMBER_HEADER_OBJ& MemberHeader)
{
    local int j <hidden=true>;
    j = 0;
    local int k <hidden=true>;
    k = 0;
    local int NameOffset <hidden=true>;
    NameOffset = LongNameBase;
    local int start <hidden=true>;
    start = 0;
 
    while(j++ < MemberHeader.index)
    {
        NameOffset += Strlen(ReadString(NameOffset)) + 1;
    }
 
    for(start = NameOffset + Strlen(ReadString(NameOffset));start >= NameOffset;start--)
    {
        if(ReadByte(start) == '\\')
        {
            break;
        }
    }
 
    return ReadString(start + 1);
}
 
//--------------------------------------
LittleEndian();
 
local int LongNameBase <hidden=true>;
 
ARCHIVE_START Start;
 
IMAGE_ARCHIVE_MEMBER_HEADER FirstLinker;
if(ReadByte(FTell() + Atoi(FirstLinker.Size)) == 10)
{
    MEMBERDATA Data(Atoi(FirstLinker.Size) + 1);
}
else
{
    MEMBERDATA Data(Atoi(FirstLinker.Size));
}
 
IMAGE_ARCHIVE_MEMBER_HEADER SecondLinker;
if(ReadByte(FTell() + Atoi(SecondLinker.Size)) == 10)
{
    MEMBERDATA Data(Atoi(SecondLinker.Size) + 1);
}
else
{
    MEMBERDATA Data(Atoi(SecondLinker.Size));
}
 
IMAGE_ARCHIVE_MEMBER_HEADER LongNames;
LongNameBase = FTell();
if(ReadByte(FTell() + Atoi(LongNames.Size)) == 10)
{
    MEMBERDATA Data(Atoi(LongNames.Size) + 1);
}
else
{
    MEMBERDATA Data(Atoi(LongNames.Size));
}
 
ALLOBJS Object;

这里讲起来有点绕,所以我会挑一些我认为的重点来说,先给大伙看些最终的效果吧,示例文件是 VS 中的 libcmt.lib。

pic05

以下是我认为的代码中的重点:

  • 必须判断成员结构的尾部是否为\n
  • 必须记录长名称的基址 LongNameBase
  • 回调函数可以访问结构体中的局部变量
  • 解析时文件指针一定不能超过文件的大小

IDA Pro + 010 Editor 反编译和修改 so 文件

当需要查看 so 源码时,可以使用 IDA Pro 对 so 文件进行反编译,然后就能阅读源码了。如果涉及到修改需求时,则可以先在 IDA Pro 工具里找到对应代码的汇编地址 ,然后使用 010 Editor 打开 so 文件,以汇编地址作为关键字进行查找,找到对应的代码,直接修改即可。

此时,切换到 IDA View-A 界面,在里面查找到 1D592,右侧的 #2 就是需要修改的值。

同样用鼠标选中 #2,然后切换到 Hex View-1 窗口,查看其十六进制的表示:

看到对应的 02 20 也被选中了,02 就是要修改的值的十六进制表示。把整个十六进制串拷贝一下,如红框圈起来所示:

然后用 010 Editor 打开 so 文件,用 ctrl+F 调出搜索框,粘贴刚刚拷贝的十六进制串,定位到对应的代码,然后将 02 改为 00

修改完后,修改后的值会显示为红色。此时记得点击 保存,然后可以关掉工具。

此时,使用 IDA Pro 再次打开 so 文件,找到刚刚的代码,发现 2 已经变成了 0。

以上就是修改流程。只演示了修改静态资源值,如果对汇编语言很熟悉,可以直接修改代码逻辑。

2、ultraedit

UltraEdit 64位绿色破解版 v30.2.0.27:https://www.xue51.com/soft/1989.html

UltraEdit 是一套非常强大的文本编辑器,它拥有编辑文本、十六进制、ASCII 码等等功能,并且内建英文单字检查、C++ 及 VB 指令突显,内置英文单字检查、代码提示、折叠等功能,同时还支持配置高亮语法和几乎所有编程语言的代码结构,可以同时打开多个文件进行编辑,即使文件比较大也不会导致它的运行速度变得很慢。

官网:https://www.ultraedit.com/catalog/#ultraedit

一、中文乱码的解决方法

1、现象问题:
同样的一个文件打开是乱码,显示文件的编码是U8-DOS,可是用EditPlus 、记事本,打开,就是正常的,编码显示是ANSI。
即使在打开文件的时候,手动选择各种编码,也不能正确显示文件内容。
2、解决方法:
高级-配置-常规,在“常规”下找到“自动检测UTF-8文件”,挑勾。确定后,把UE关了,再重开。你的文本就能正常显示了,试试吧。

二、删除空行

如何在 UltraEdit 删除空行(含空格,制表符),打开软件,ctrl+r弹出替换对话框,点选启用正则表达式
方法1:
1、在查找框输入 ^p^p:
2、在替换框输入 ^p
3、执行全部替换;
4、这种方法是对连续的两个回车换行,替换成一个回车换行;如果空行中含有空格或者制表符,则不能处理;
方法2:
1、查找框中输入:%[ ^t]++^p,注意^t之前有空格
2、在替换框什么也输入
3、执行全部替换;
4、这种方法可以处理方法1中的缺陷

三、如何设置自动换行

有时候这会非常麻烦, 要让自动换行请按发下方法:
1、点击菜单栏的“高级→配置”,找到“编辑器→自动换行/制表符设置”。
2、然后,把“默认为每个文件启用自动换行”,这样就可以了。 还有一种临时的让软件自动换行的方法就是按下: Ctrl+W,这种方法下次再启动UltraEdit,还是不能自动换行。

四、切换到传统菜单模式

UltraEdit 是一套功能强大的文本编辑器,可以编辑文本、十六进制、ASCII 码,完全可以取代记事本。新的版本安装后界面为 RIbbon 风格,比较占空间,如果电脑屏较小的话,则编辑界面较小。可以改为传统风格模式,图标更小,空间更大。

步骤:打开 ultraedit 后,在工具栏空白处点击右键 ---> 在弹出的右键菜单中,点击工具栏菜单模式 ---> 选择传统模式功能即可。

使用 UltraEdit

UltraEdit 支持二进制和16进制编辑,所以还可以用来修改EXE 或DLL 文件。

列模式

列模式能让您按列选取和编辑数据,而一般编辑器只能按行选择数据。

使用快捷键 Alt+C,或者使用菜单 列->列模式。进入列模式后,通过按下键盘上的SHIFT键和方向键来选择多列,光标变成了多列光标。如果敲入的是英文字母或字符是没有问题,当在列模式下敲入的是汉字的时候会出现乱码,因此可以用插入/填充列这个功能来解决这个问题。

插入/填充列

在列模式下选择要填充的列,选择菜单 列->插入/填充列,然后出现一个对话框,在这里填写要插入的文字后点”确定”。

排序(Sort)

排序是UltraEdit提供的非常实用的一个功能,也许您会觉得用Excel更方便,但别忘了Excel只能支持65535行数据,而UltraEdit处理上百万行的数据也不成问题,功能决不逊色于Excel。

菜单 ---> 文件 ---> 排序 ---> 高级排序/选项

排列顺序:可以选择是升序还是降序

删除重复项:可以将文件中一模一样的行删除,只保留一行。(想想用Excel怎么去除重复项)

数字排序:当要排序的列是数字,并且关心它的实际大小时需要勾选这一项,下面的示例将说明这个问题。

排序列:一共可以设置4个列,通过起始列和结束列来指定。

正则表达式搜索与替换

  • Ctrl+F 在弹出的查找对话框中输入表达式,并且勾选”正则表达式”
  • Ctrl+R 调出替换对话框

UltraEdit中,正则表达式被很好地支持,目前的版本中一共支持三种,UltraEdit风格正则表达式、Unix风格正则表达式和Perl兼容正则表达式,本文介绍Perl兼容正则表达式,这是一条被广泛使用的正则表达式,绝大多数的编程语言都支持这种表达式。

要使用Perl兼容正则表达式,需要在UltraEdit中做一下设置。点击菜单 高级->配置,出现下图的对话框,在左侧选中”正则表达式引擎”,右边勾选”Perl兼容正则表达式”。

正则表达式语法

元字符说明
匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符()
\d 匹配数字
\b 匹配单词的开始或结束
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
匹配行首
匹配行尾

如果查找元字符本身的话,需要使用 \ 来转义。

语法说明
重复零次或更多次
重复一次或更多次
重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

若要匹配 aeiou 五个字符中的任意一个,可以表示成 [aeiou]。再如 [0-9] 表示0到9之间的任意一个数字,它的含义和元字符中的 \d 实际上是一样的。

反意:如果要匹配非a则 [^a] ,除 aeiou 五个字母之外的表示成 [^aeiou]

贪婪与止贪

有字符串 dveadebcadefboipi,正则表达式 a.*b,表达式的意思是匹配由a开始中间包含任意多个字符并以b结尾,这个表达式匹配出来的结果是adebcadefb,而不会是adeb,我们称这种匹配为贪婪匹配,因为它匹配了尽可能多的字符。要防止这种贪婪匹配,使用 ?,把上面的表达式写成a.*?b 则匹配出来的结果就是 adeb ,这就是 "止贪匹配"

示例:很多日期,都是这样的格式dd/mm/yyyy,我们希望把他替换成yyyy-mm-dd的格式。既然是替换,那么必需先查到目标串,用\d表示数据,月和日都一位或两位数据组成,正则表达式表示为\d{1,2},年份都四个数字表示为\d{4},加上中间的分隔符/,整个日期串可以表示为\d{1,2}/\d{1,2}/\d{4}。我们替换的目标是要把最后的年份放到第一位去,因此还需要这个搜索能返回各个部分的值,在Perl正则表达式中用()可以返回搜索串中的值,并用$1表示第一个括号中的值,因此我们加上3个括号表达式变成(\d{1,2})/(\d{1,2})/(\d{4}),那么$1表于日,$2表示月,$3表示年。说到这里要达到我们的目标就很简单了。按下键盘上的Ctrl+R调出替换对话框,查找内容为(\d{1,2})/(\d{1,2})/(\d{4}),替换为$3-$2-$1,记得勾上”正则表达式”。

常用的正则表达

行首空格: ^\s+
行尾空格:\s+$
IP地址:[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
正整数: ^[1-9]\d*$
负整数: ^-[1-9]\d*$

远程文件直接编辑

要编辑Linux上的文件是一件很痛苦的使用,Linux上的VI编辑器可不像UltraEdit这么好用,在没有UltraEdit前也许您只能把文件下载回来编辑好后再传上来,有了UltraEdit的话不需要这么麻烦了,他直接打开远程机器上的文件,保存后自动上传到远程服务器。

步骤:菜单 ---> 文件 ---> FTP/Telnet ---> 从FTP打开

注意:不建议使用该功能编辑系统核心文件,保存的时候如果出现网络故障容易导致文件丢失。

冻结窗口

实现上UltraEdit中并没有冻结窗口这个概念,之所以这么中是因为UltraEdit可以实现类似Excel的冻结窗口的功能。在Excel中我们常用这个功能来固定表头,这样上下滚动的时候可以保持表头不动。

UltraEdit中可以实际固定左侧列,滚动水平条的时候只有右边动。例如一个书目文件,第一列是书名,而价格这一列在最后,中间夹着很多内容,当把价格这一类滚动到视图中间的时候却看不到书名。因此我们想把书名这一列固定下来,在滚动水平条的时候固定不动,先要设置一个列标记,点菜单 视图->设置列标记,在出现的设置列标记对话框中,勾选要冻结的列,设好后,点”确定”,这样 冻结的列的内容在水平条滚动的时候不会变,可以把后面的内容滚到前面来

语法加亮

语法加亮是UltraEdit的一个突出亮点,它能像各种语言的IDE开发环境一样,对各种语法的关键字着色。UltraEdit通过一个叫wordfile的文件来定义各种语言的着色规则。通过添加语法规则即可增加UltraEdit的识别能力。

默认安装后的UltraEdit不支持Oracle的SQL语法着色,下面举例如何让UltraEdit识别Oracle的SQL脚本并对关键字着色。

首先打开wordfile定义文件,点菜单 高级->配置,在左侧找到”语法加亮”,点右边的”打开”按钮即可打开wordfile文件。

到官方网站下载Oracle的语法定义文件,官方提供了上百种语法的定义文件,可以根据需要下载,路径为http://www.ultraedit.com/downloads/extras.html#wordfiles

把下载回来的文件粘在wordfile的结尾保存一下就行了

注意一下,下回来内容的开头有一个/L后面有个数字,这个数据需要根据自己的情况改变一下。这是一个编号,不能和wordfile已有的编号重复,并且不能大于20。您可以通过以下方法确定这个编号,点一下工具栏上的”查看方式”按钮,

弹出下图的菜单,红色框内语言15到语言20都是目前系统没有用到的编号,因此在这里我们可以把这个编号改成15。保存后,当我们再次打开Oracle的SQL脚本的时候,语法中的关键字已经会自动着色了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值