Sigil 基础教程(二):Sigil 的基本操作

【内容简介】介绍Sigil的基本操作。主要有以下知识点:

  • 文本导入
  • 查找替换功能
  • 搜索模板功能
  • 插入图片
  • 制作目录
  • 选定封面

———————-

【相关知识】Sigil正则表达式入门

正则表达式,是一种用特殊符号表示文字的方法,主要用在查找和替换方面。下面的例子可以让你知道正则表达式是干什么用的。在一个文本中,有这样的一些内容:

序章
第一章 ABCDEF
第二章 GHIJKL
第三章 …………
终章

这种内容我们都很熟悉,你有没有想过,用什么办法可以把这些内容一次过查找出来呢?为了简化,我们先来看这个部分。

第一章
第二章
第三章

可以看到,这些内容有着极高的相似性,由“第”,“章”开头和结尾,中间有着一些数字。如果我们能用一个什么符号来代表中间的所有字,比如一个圆点“.”,不就可以用这样的方式来查找出所有这样的内容了吗。

第.章

很早之前,就有人发明了一套完整的方案,让我们可以用各种不同的符号来达到这种目的,那就是我们将要了解的正则表达式。

正则表达式作为一种描述字符的方案,在大量软件、编程语言中都有所运用,而在这些不同的平台上,正则表达式的使用方式又往往会有或多或少的差异,在某个平台上管用的表达式,换个地方可能就要改改才能正确运行。那么在这篇文章里,我们主要是讲 Sigil 中的正则表达式,至于推广应用,就要靠大家去查找资料了。

1. 元字符

我们前面提到,正则表达式一个重要作用就是用特别的符号来代表一类字符,而这些符号就叫做“元字符”。这些元字符在大多数环境下都是通用的。注意,元字符中所有符号都是半角符号,也就是通常说的英文符号。以下是一些常见的元字符,实际上还有更多。这些元字符都经过测试,在 Sigil 下有效。

符号 意义 说明
. 任意一个字符 最简单的元字符,匹配任意字符,但不包括换行符 \n
\ 转义 把元字符改变为普通字符,或者把某些普通字符转变为元字符。比如,\. 就是代表普通的点号,不代表其他字符。
\s 空白字符 半角空格、制表符等空白字符。在 Sigil 中还能匹配到换行符 \n 和空白行,使用要注意。注意,不能匹配到全角空格。
\t 制表符 匹配制表符。
\n 换行符 表示文章的换行,这是一个不可见符号,在例子中,这个符号在 _ 的位置。

aaa_
bbb

你能够通过 \n 找到换行符,但不能够插入换行符。要在替换结果中换行,需要用 \r

\r 回车 代表一个回车符。这个符号不会在文本中出现,因此不能查找到。但是如果你需要在查找结果中插入一个换行,那么就要用 \r。注意,插入后在文本中出现的仍然会是 \n 而不是 \r
\d 任意一个阿拉伯数字 也就是可以代表 0~9 中的任意一个。
\D 任意一个非阿拉伯数字 0~9 以外的字符,同样的,不包括换行符 \n
^ 行首 即一行的开头。Sigil 中不能单独使用,要配合其他字符。比如,^a 表示在行首的“a”,能匹配到第一行和第三行的字母“a”。第二行因为行首是空格,因此匹配不到。

abc
abc
abcd
$ 行尾 表示任意一行的结尾,不包括换行符。在 Sigil 中不能单独使用。比如,c$ 表示位于行尾的 c,能够匹配到第一行和第二行的字母 c

abc
abc
abcd
+ 一或更多 表示一个或更多。必须配用其他字符使用。添加在一个字符后面,表示一个或更多个该字符。相当于 {1,}。比如,a+ 表示一个以上连续的“a”,以下例子都能匹配到。

a
aa
aaa
? 尽可能少 表示尽可能少。必须配合其他字符使用。比如,“accccbb”中 a.*b 匹配到“accccbb”,而 a.*?b 就能只匹配到“accccb”。注意:在某些平台的正则表达式中,这一功能很可能由 - 减号提供。
| 一个逻辑选择符。aa|bb 既可以匹配到“aa”也可以匹配到“bb”。可以用到多个选项中,比如 aa|bb|cc1|2|3 相当于 [123]
* 尽可能多 即无或更多。相当于 {0,}
{n,m} 个数范围 表示匹配项的个数范围。比如,a{3} 表示“aaa”,a{2,4} 表示“aa”或“aaa”或“aaaa”,a{1,} 表示一个以上的“a”。注意,a{,2} 应该表示两个以下的“a”,但是这种写法在 Sigil 中无效,要写成 a{0,2}
[] 包含 [] 本身匹配一个字符。比如,[abc] 匹配“a”、“b”或“c”。通常不分顺序,[abc][bca] 一样。[] 中用 - 表示范围,[a-z] 表能匹配到“a”到“z”全部 26 个字母之一。比如,[0-9]\d 是一样的,但是 \d 速度更快。如果要在 [] 中匹配 - 本身,把 - 写在最前面,或者把它转义 \-。比如 [-0-9],就能匹配所有阿拉伯数字和“-”。
[^] 不包含 [] 的逆操作。比如 a[^b]c,能匹配到第二行,第三行。

abc
adc
afc

注意,因为 [] 中符号是无序的,因此如果要排除字符串,要用其他方法。

() 捕获组 (abc) 表示把“abc”分为一组。分组后可以配合其他元字符使用。一个组称为一个捕获组。比如,(abc)+ 就是一个或以上“abc”组合的意思。捕获组中的内容会被记录并编号,可以通过 \0\1 这种形式来引用。
(?:) 分组/非捕获组 作用上与 () 类似,能把内容分为一组,但 (?:) 仅有分组功能,不记录匹配内容。也就是说,无法通过 \0\1 等方式引用。此元字符虽然消耗的资源更少,速度更快,在简单应用中可能体验不到与 () 的区别。
\0
\1
\2
反向引用 配合分组使用,引用一个分组。比如,在查找时有分组 (abc),那么 \1 就代表“abc”。有分组 a(bc)(de)f,那么 \0 代表“abcdef”,\1 代表“bc”,\2 代表“de”。如此类推。
嵌套也是一样的,比如 (abc(def))\1 代表“abcdef”,\2 代表“def”。同样地,也能在查找时应用。比如有字符串“abc111abc”,那么表达式 (abc).*\1 就能匹配到所有内容。

* 注:在其他平台中,可能使用的是$0,$1等表示方法。

(?s) 多行匹配 放在表达式的最前端,使得 . 可以匹配到 \n,从而实现跨行匹配。比如以下例子:

<div></div>
  <h1></h1>
<div></div>

使用正则表达式 <div>.*</div> 一次只能匹配到第一行或者第三行。而使用 (?s)<div>.*</div> 则能一次性匹配到第一行到第三行所有内容。

* 注1:这是 Sigil 特有元字符,其他平台有另外的方法实现该功能。
* 注2:此前缀和勾选“DotAll”效果一致。

(?U) 最少匹配 放在表达式的最前端,使得整个正则表达式实现最少匹配。比如以下例子:

<div>AAA<div>BBB</div>CCC</div>

正则表达式 <div>.*</div> 会匹配到整个句子。而 (?U)<div>.*</div> 只会匹配到 <div>AAA<div>BBB</div>

* 注1:这是 Sigil 特有元字符,其他平台有另外的方法实现该功能。
* 注2:此前缀和勾选“Minimal Match”效果一致。

2. 常用正则表达式

在这一部分,我们回来看一些很常用的正则表达式,这些表达式往往是更复杂表达式的组成部分。

2.1 所有字符

.*

匹配所有内容。. 代表一个字符,* 代表任意多个,因此 .* 代表“所有字符”。比如

<div>.*</div>

表示 <div> 标签内的所有内容,可以依次匹配到下列各项

<div>AAACCCC</div>
<div></div>
<div>!!!!AAAAACCCC啊啊啊啊</div>

但不能跨行,这样是匹配不到的:

<div>
  AAAAAA
</div>

如果要跨行,需要使用 (?s)

2.2 空白行

^[ \t ]*$\n

匹配空白行的典型写法。可以匹配无内容的行,只有空格的行,只有制表符的行或者空格和制表符混合排列的行。[] 中包括的分别是空格“ ”,制表符 \t 和全角空格“ ”。也可以根据需要添加更多的字符。

2.3 行尾空白字符

[ \t ]+$

匹配出现在行尾的空白字符,比如空格。思路和 2.2 一致,使用 $ 把搜查范围限定在结尾,使用了符号 + 确保最少有一个空白字符,否则会查找失败。

2.4 压缩重复符号

查找:

。+

替换:

很容易理解,把一个以上的“。”,换成一个“。”,从而达到压缩重复符号的目的。可以灵活改变,压缩各种重复的字符。配合 2.2 的查找空白行,也能实现压缩空白行。

3. 应用实例

在这一部分,我们会看一些 Sigil 使用过程中实际会用到的例子,方便各位了解正则表达式的使用。

3.1 添加标签

你打算为所有的图片添加一个 <div>,并且 class 为 images。

原语句 <img src="Images/001.jpg" />
目标语句 <div class="images"><img src="Images/001.jpg" /></div>
使用元字符 .
*
\0
查找 <img.*/>
替换 <div class="images">\0</div>

解说:

查找以 <img 开头,/> 结尾的所有句子,这个表达式默认分组为 0,因此可以用 \0 来引用。如果你的文本中图片语句必定是独立一行的,可以直接使用 <img 这样的简单句子。同样的,也可以通过 /> 后面是否紧跟换行符 \n 来判断图片是否独立一行,从而实现不同位置图片的匹配。

扩展:

同样的,你可以用这个方法为各种内容很方便的添加标签,如果你常常用到这样的替换,不要忘记善用 Sigil 的搜索模板功能。

3.2 拼接断行

在一些文本中,会存在断行,我们要把这些断行重新拼接起来。

原文本 床前
明月光,
疑是地上
霜。
举头望
明月,
低头思故乡。
目标文本 床前明月光,
疑是地上霜。
举头望明月,
低头思故乡。
使用元字符 [^]\n
查找 ([^,。])$\n
替换 \1

解说:

其实所谓的断行,就是在不该换行的地方进行了换行,那么只要分析出不该换行的特征就可以了。在这个例子中,换行只应该出现在“,”和“。”后面,因此我们查找前面没有“,”或者“。”的换行,并且将其删除就可以了。

因为使用的正则表达式会匹配到 \n 前面的一个字符,为了不把这个字符也删除,所以要用 () 把这个字符保护起来。

扩展:

实际上我们还可以使用“零宽断言(Zero-width assertions 或 Zero-Length Assertions)”来达到这个效果,写法是 (?<![,。]$)\n,直接替换为空,零宽断言本身就保护了字符。但是作为一个入门应用,我还是先介绍使用 [^] 的方法,关于零宽断言,有兴趣的朋友可以到这个网址了解:

https://www.regular-expressions.info/lookaround.html

3.3 识别章节标题

这是很常见的一个需求,我们往往要为章节标题添加 <h1><h2> 之类的标签。通过 3.1 我们已经了解到如何添加标签,因此这里着重讲解如何识别标题。

原文本 序章

第一章 XXXX
第二章 CCCC
第三章 AAAA
终章
后记
目标文本
<h1>序章</h1>
<h1>第一章 XXXX</h1>
<h1>第二章 CCCC</h1>
<h1>第三章 AAAA</h1>
<h1>终章</h1>
<h1>后记</h1>
使用元字符 .
*
[]
()
\1
^
|
{m,n}
查找 ^((序章|第.{1,3}章|终章|后记).*)
替换 <h1>\1</h1>

解说:

表达式开始的 ^ 查找内容必须是每一行的开头,这样才不会匹配到正文中的“第N章”之类的内容。当然,还是无法完全排除匹配到正文的可能性,因此要注意替换次数,如果次数和章节数目不符,就要留意了。

通过 | 的使用,我们可以在一个表达式中就匹配到所有的内容,要善用 |第.{1,3}章 是一个保险,最多匹配到“第九十九章”这样的字符串,在实际使用中,往往只需要写 第.章。如果是“第1章”这样的,就可以用 第\d章 来更精准的匹配。

3.5 自动插入 <title></title> 内容

原文本
<title></title>
</head>
<body>
<h1>XXXX</h1>
目标文本
<title>XXXX</title>
</head>
<body>
<h1>XXXX</h1>
使用元字符 .
*
()
\1
\2
(?s)
\n
\r
查找 (?s)<title></title>\n(.*<h1>(.*)</h1>)
替换 <title>\2</title>\r\1

解说:

通说 () 的捕获群获取所需要的字符串,然后以逆向引用来达到插入内容的目的。使用 Sigil 的前置符 (?s) 使得 .* 可以匹配到换行符 \n,因此表达式可以匹配到 </head><h1> 之间的所有内容。捕获组 1 保留 <title> 以外的所有内容,以便稍后恢复,捕获组 2 获取 <h1> 中的内容,插入到 <title> 中去。这个操作在 Sigil 中比较有用,因为 Sigil 默认是不会填写 <title> 内容的。

———————

原文链接:http://www.cnepub.com/discuz/thread-161771-1-1.html

未经允许不得转载:书路 » Sigil 基础教程(二):Sigil 的基本操作

赞 (0) 打赏