蚊章汇 - Sylvain Leroux
type: channel
link: https://linuxcn.bwsl.wang/author/817/
description: Sylvain Leroux
items: 文字间的战斗与其救世主 Unicode
items: Sed 命令完全指南
items: Linux 下 cut 命令的 4 个基础实用的示例
items: 详解如何用源代码安装软件，以及如何卸载它

文字间的战斗与其救世主 Unicode
type: item
date: 2023-01-27T20:35:27+08:00
description: 我们都知道如何从键盘输入文字，不是吗？那么，请允许我挑战你在你最爱的文本编辑器中输入这段文字：这段文字难以被输入因为它包含着：键盘上没有的印刷符号，平假名日文字符，为符合平文式罗马字标准，日本首都的名字中的两个字母 “o” 头顶带有长音符号，以及最后，用西里尔字母拼写的名字德米特里。毫无疑问，想要在早期的电脑中输入这样的句子是不可能的。这是因为早期电脑所使用的字符集有限，无法兼容多种书写系统。而如今类似的限制已不复存在，马上我们就能在文中看到。电脑是如何储存文字的？计算机将字符作为数字储存。它们再通过表格将这些数字与含有意义的字形一一对应。在很长一段时间里，计算机将每个字符作为 0 到 255 之间的数字储存（这正好是一个字节的长度）。但这用来代表人类书写所用到的全部字符是远远不够的。而解决这个问题的诀窍在于，取决于你住在地球上的哪一块区域，系统会分别使用不同的对照表。这里有一张在法国常被广泛使用的对照表 ISO 8859-15：如果你住在俄罗斯，你的电脑大概会使用 KOI8-R 或是 Windows-1251 来进行编码。现在让我们假设我们在使用后者：对于 128 之前的数字，两张表格是一样的。这个范围与 US-ASCII 相对应，这是不同字符表格之间的最低兼容性。而对于 128 之后的数字，这两张表格则完全不同了。比如，依据 Windows-1251，字符串 “said Дмитрий” 会被储存为：115 97 105 100 32 196 236 232 242 240 232 233 按照计算机科学的常规方法，这十二个数字可被写成更加紧凑的十六进制：73 61 69 64 20 c4 ec e8 f2 f0 e8 e9 如果德米特里发给我这份文件，我在打开后可能会看到：said Äìèòðèé 这份文件 看起来 被损坏了，实则不然。这些储存在文件里的数据，即数字，并没有发生改变。被显示出的字符与 另一张表格 中的数据相对应，而非文字最初被写出来时所用的编码表。让我们来举一个例子，就以字符 “Д” 为例。按照 Windows-1251，“Д” 的数字编码为 196（c4）。储存在文件里的只有数字 196。而正是这同样的数字在 ISO8859-15 中与 “Ä” 相对应。这就是为什么我的电脑错误地认为字形 “Ä” 就是应该被显示的字形。多提一句，你依然可以时不时地看到一些错误配置的网站展示，或由 用户邮箱代理 发出的对收件人电脑所使用的字符编码做出错误假设的邮件。这样的故障有时被称为乱码（LCTT 译注：原文用词为 mojibake， 源自日语 文字化け）。好在这种情况在今天已经越来越少见了。Unicode 拯救了世界我解释了不同国家间交换文件时会遇到的编码问题。但事情还能更糟，同一个国家的不同生产商未必会使用相同的编码。如果你在 80 年代用 Mac 和 PC 互传过文件你就懂我是什么意思了。也不知道是不是巧合，Unicode 项目始于 1987 年，主导者来自 施乐 Xerox 和…… 苹果 Apple 。这个项目的目标是定义一套通用字符集来允许同一段文字中 同时 出现人类书写会用到的任何文字。最初的 Unicode 项目被限制在 65536 个不同字符（每个字符用 16 位表示，即每个字符两字节）。这个数字已被证实是远远不够的。于是，在 1996 年 Unicode 被扩展以支持高达 100 万不同的 代码点 code point 。粗略来说，一个“代码点”可被用来识别字符表中的一个条目。Unicode 项目的一个核心工作就是将世界上正在被使用（或曾被使用）的字母、符号、标点符号以及其他文字仓管起来，并给每一项条目分配一个代码点用以准确分辨对应的字符。这是一个庞大的项目：为了让你有个大致了解，发布于 2017 年的 Unicode 版本 10 定义了超过 136,000 个字符，覆盖了 139 种现代和历史上的语言文字。随着如此庞大数量的可能性，一个基本的编码会需要每个字符 32 位（即 4 字节）。但对于主要使用 US-ASCII 范围内字符的文字，每个字符 4 字节意味着 4 倍多的储存需求以及 4 倍多的带宽用以传输这些文字。所以除了 UTF-32，Unicode 联盟还定义了更加节约空间的 UTF-16 和 UTF-8 编码，分别使用了 16 位和 8 位。但只有 8 位该如何储存超过 100,000 个不同的值呢？事实是，你不能。但这其中窍门在于用一个代码值（UTF-8 中的 8 位以及 UTF-16 中的 16 位）来储存最常用的一些字符。再用几个代码值储存最不常用的一些字符。所以说 UTF-8 和 UTF-16 是 可变长度 编码。尽管这样也有缺陷，但 UTF-8 是空间与时间效率之间一个不错的折中。…

Sed 命令完全指南
type: item
date: 2018-11-15T03:06:00+08:00
description: 在前面的文章中，我展示了 Sed 命令的基本用法， Sed 是一个实用的流编辑器。今天，我们准备去了解关于 Sed 更多的知识，深入了解 Sed 的运行模式。这将是你全面了解 Sed 命令的一个机会，深入挖掘它的运行细节和精妙之处。因此，如果你已经做好了准备，那就打开终端吧，下载测试文件 然后坐在电脑前：开始我们的探索之旅吧！关于 Sed 的一点点理论知识首先我们看一下 sed 的运行模式要准确理解 Sed 命令，你必须先了解工具的运行模式。当处理数据时，Sed 从输入源一次读入一行，并将它保存到所谓的 模式空间 pattern space 中。所有 Sed 的变换都发生在模式空间。变换都是由命令行上或外部 Sed 脚本文件提供的单字母命令来描述的。大多数 Sed 命令都可以由一个地址或一个地址范围作为前导来限制它们的作用范围。默认情况下，Sed 在结束每个处理循环后输出模式空间中的内容，也就是说，输出发生在输入的下一个行覆盖模式空间之前。我们可以将这种运行模式总结如下：尝试将下一个行读入到模式空间中如果读取成功：按脚本中的顺序将所有命令应用到与那个地址匹配的当前输入行上如果 sed 没有以静默模式（-n）运行，那么将输出模式空间中的所有内容（可能会是修改过的）。重新回到 1。因此，在每个行被处理完毕之后，模式空间中的内容将被丢弃，它并不适合长时间保存内容。基于这种目的，Sed 有第二个缓冲区： 保持空间 hold space 。除非你显式地要求它将数据置入到保持空间、或从保持空间中取得数据，否则 Sed 从不清除保持空间的内容。在我们后面学习到 exchange、get、hold 命令时将深入研究它。Sed 的抽象机制你将在许多的 Sed 教程中都会看到上面解释的模式。的确，这是充分正确理解大多数基本 Sed 程序所必需的。但是当你深入研究更多的高级命令时，你将会发现，仅这些知识还是不够的。因此，我们现在尝试去了解更深入的一些知识。的确，Sed 可以被视为是抽象机制的实现，它的状态)由三个缓冲区 、两个寄存器和两个标志来定义的：三个缓冲区用于去保存任意长度的文本。是的，是三个！在前面的基本运行模式中我们谈到了两个：模式空间和保持空间，但是 Sed 还有第三个缓冲区： 追加队列 append queue 。从 Sed 脚本的角度来看，它是一个只写缓冲区，Sed 将在它运行时的预定义阶段来自动刷新它（一般是在从输入源读入一个新行之前，或仅在它退出运行之前）。Sed 也维护两个寄存器： 行计数器 line counter （LC）用于保存从输入源读取的行数，而 程序计数器 program counter （PC）总是用来保存下一个将要运行的命令的索引（就是脚本中的位置），Sed 将它作为它的主循环的一部分来自动增加 PC。但在使用特定的命令时，脚本也可以直接修改 PC 去跳过或重复执行程序的一部分。这就像使用 Sed 实现的一个循环或条件语句。更多内容将在下面的专用分支一节中描述。最后，两个标志可以修改某些 Sed 命令的行为： 自动输出 auto-print （AP）标志和<ruby替换 substitution（SF）标志。当自动输出标志 AP 被设置时，Sed 将在模式空间的内容被覆盖前自动输出（尤其是，包括但不限于，在从输入源读入一个新行之前）。当自动输出标志被清除时（即：没有设置），Sed 在脚本中没有显式命令的情况下，将不会输出模式空间中的内容。你可以通过在“静默模式”（使用命令行选项 -n 或者在第一行或脚本中使用特殊注释 #n）运行 Sed 命令来清除自动输出标志。当它的地址和查找模式与模式空间中的内容都匹配时，替换标志 SF 将被替换命令（s 命令）设置。替换标志在每个新的循环开始时、或当从输入源读入一个新行时、或获得条件分支之后将被清除。我们将在分支一节中详细研究这一话题。另外，Sed 维护一个进入到它的地址范围（关于地址范围的更多知识将在地址范围一节详细描述）的命令列表，以及用于读取和写入数据的两个文件句柄（你将在读取和写入命令的描述中获得更多有关文件句柄的内容）。一个更精确的 Sed 运行模式一图胜千言，所以我画了一个流程图去描述 Sed 的运行模式。我将两个东西放在了旁边，像处理多个输入文件或错误处理，但是我认为这足够你去理解任何 Sed 程序的行为了，并且可以避免你在编写你自己的 Sed 脚本时浪费在摸索上的时间。你可能已经注意到，在上面的流程图上我并没有描述特定的命令动作。对于命令，我们将逐个详细讲解。因此，不用着急，我们马上开始！打印命令打印命令（p）是用于输出在它运行那一刻模式空间中的内容。它并不会以任何方式改变 Sed 抽象机制中的状态。示例：sed -e 'p' inputfile上面的命令将…

Linux 下 cut 命令的 4 个基础实用的示例
type: item
date: 2018-08-04T07:29:00+08:00
description: cut 命令是用来从文本文件中移除“某些列”的经典工具。在本文中的“一列”可以被定义为按照一行中位置区分的一系列字符串或者字节，或者是以某个分隔符为间隔的某些域。先前我已经介绍了如何使用 AWK 命令。在本文中，我将解释 linux 下 cut 命令的 4 个本质且实用的例子，有时这些例子将帮你节省很多时间。Linux 下 cut 命令的 4 个实用示例假如你想，你可以观看下面的视频，视频中解释了本文中我列举的 cut 命令的使用例子。https://www.youtube.com/PhE_cFLzVFw1、 作用在一系列字符上当启用 -c 命令行选项时，cut 命令将移除一系列字符。和其他的过滤器类似， cut 命令不会直接改变输入的文件，它将复制已修改的数据到它的标准输出里去。你可以通过重定向命令的结果到一个文件中来保存修改后的结果，或者使用管道将结果送到另一个命令的输入中，这些都由你来负责。假如你已经下载了上面视频中的示例测试文件，你将看到一个名为 BALANCE.txt 的数据文件，这些数据是直接从我妻子在她工作中使用的某款会计软件中导出的：sh$ head BALANCE.txt ACCDOC ACCDOCDATE ACCOUNTNUM ACCOUNTLIB ACCDOCLIB DEBIT CREDIT 4 1012017 623477 TIDE SCHEDULE ALNEENRE-4701-LOC 00000001615,00 4 1012017 445452 VAT BS/ENC ALNEENRE-4701-LOC 00000000323,00 4 1012017 4356 PAYABLES ALNEENRE-4701-LOC 00000001938,00 5 1012017 623372 ACCOMODATION GUIDE ALNEENRE-4771-LOC 00000001333,00 5 1012017 445452 VAT BS/ENC ALNEENRE-4771-LOC 00000000266,60 5 1012017 4356 PAYABLES ALNEENRE-4771-LOC 00000001599,60 6 1012017 4356 PAYABLES FACT FA00006253 - BIT QUIROBEN 00000001837,20 6 1012017 445452 VAT BS/ENC FACT FA00006253 - BIT QUIROBEN 00000000306,20 6 1012017 623795 TOURIST GUIDE BOOK FACT FA00006253 - BIT QUIROBEN 00000001531,00 上述文件是一个固定宽度的文本文件，因为对于每一项数据，都使用了不定长的空格做填充，使得它看起来是一个对齐的列表。这样一来，每一列数据开始和结束的位置都是一致的。从 cut 命令的字面意思去理解会给我们带来一个小陷阱：cut 命令实际上需要你指出你想保留的数据范围，而不是你想移除的范围。所以，假如我只需要上面文件中的 ACCOUNTNUM 和 ACCOUNTLIB 列，我需要这么做：sh$ cut -c 25-59 BALANCE.txt | head ACCOUNTNUM ACCOUNTLIB 623477 TIDE SCHEDULE 445452 VAT BS/ENC 4356 /accountPAYABLES 623372 ACCOMODATION GUIDE 445452 VAT BS/ENC 4356 PAYABLES 4356 PAYABLES 445452 VAT BS/ENC 623795 TOURIST GUIDE BOOK 范围如何定义？正如我们上面看到的那样， cut 命令需要我们特别指定需要保留的数据的范围。所以，下面我将更正式地介绍如何定义范围：对于 cut 命令来说，范围是由连字符(-)分隔的起始和结束位置组成，范围是基于 1 计数的，即每行的第一项是从 1 开始计数的，而不是从 0 开始。范围是一个闭区间，开始和结束位置都将包含在结果之中，正如它们之间的所有字符那样。如果范围中的结束位置比起始位置小，则这种表达式是错误的。作为快捷方式，你可以省略起始或结束值，正如下面的表格所示：范围含义a-ba 和 b 之间的范围（闭区间）a与范围 a-a 等价-b与范围 1-a 等价b-与范围 b-∞ 等价cut 命令允许你通过逗号分隔多个范围，下面是一些示例：# 保留 1 到 24 之间（闭区间）的字符 cut -c -24 BALANCE.txt # 保留 1 到 24（闭区间）以及 36 到 59（闭区间）之间的字符 cut -c…

详解如何用源代码安装软件，以及如何卸载它
type: item
date: 2017-12-26T05:50:37+08:00
description: 简介：这篇文章详细介绍了在 Linux 中怎么用源代码安装程序，以及怎么去卸载用源代码安装的程序。Linux 发行版的一个最大的优点就是它的包管理器和相关的软件库。通过它们提供的资源和工具，你才能够以完全自动化的方式在你的计算机上下载和安装软件。但是，尽管付出了很多的努力，包维护者仍然没法照顾好每种情况，也不可能将所有的可用软件都打包进去。因此，仍然存在需要你自已去编译和安装一个新软件的情形。对于我来说，到目前为止，最主要的原因是，我编译一些软件是我需要去运行一个特定的版本。或者是我想去修改源代码或使用一些想要的编译选项。如果你也属于后一种情况，那你已经知道你应该怎么做了。但是，对于绝大多数的 Linux 用户来说，第一次从源代码中编译和安装一个软件看上去像是一个入门仪式：它让很多人感到恐惧；但是，如果你能克服困难，你将可能进入一个全新的世界，并且，如果你做到了，那么你将成为社区中享有特权的一部分人。建议阅读：怎样在 Ubuntu 中安装和删除软件（完全指南）A. 在 Linux 中从源代码开始安装软件这正是我们要做的。因为这篇文章的需要，我要在我的系统上安装 NodeJS 8.1.1。它是个完全真实的版本。这个版本在 Debian 仓库中没有：sh$ apt-cache madison nodejs | grep amd64 nodejs | 6.11.1~dfsg-1 | http://deb.debian.org/debian experimental/main amd64 Packages nodejs | 4.8.2~dfsg-1 | http://ftp.fr.debian.org/debian stretch/main amd64 Packages nodejs | 4.8.2~dfsg-1~bpo8+1 | http://ftp.fr.debian.org/debian jessie-backports/main amd64 Packages nodejs | 0.10.29~dfsg-2 | http://ftp.fr.debian.org/debian jessie/main amd64 Packages nodejs | 0.10.29~dfsg-1~bpo70+1 | http://ftp.fr.debian.org/debian wheezy-backports/main amd64 Packages 第 1 步：从 GitHub 上获取源代码像大多数开源项目一样，NodeJS 的源代码可以在 GitHub：https://github.com/nodejs/node 上找到。所以，我们直接开始吧。如果你不熟悉 GitHub，git 或者提到的其它 版本管理系统包含了这个软件的源代码，以及多年来对该软件的所有修改的历史。甚至可以回溯到该软件的最早版本。对于开发者来说，保留它的历史版本有很多好处。如今对我来说，其中一个好处是可以得到任何一个给定时间点的项目源代码。更准确地说，我可以得到我所要的 8.1.1 发布时的源代码。即便从那之后他们有了很多的修改。在 GitHub 上，你可以使用 “branch” （分支）按钮导航到这个软件的不同版本。“分支” 和 “标签” 是 Git 中一些相关的概念。总的来说，开发者创建 “分支” 和 “标签” 来在项目历史中对重要事件保持跟踪，比如当他们启用一个新特性或者发布一个新版本时。在这里先不详细介绍了，你现在只需要知道我在找被标记为 “v8.1.1” 的版本。在选择了 “v8.1.1” 标签后，页面被刷新，最显著的变化是标签现在作为 URL 的一部分出现。另外，你可能会注意到文件改变日期也有所不同。你现在看到的源代码树是创建了 v8.1.1 标签时的代码。在某种意义上，你也可以认为像 git 这样的版本管理工具是一个时光穿梭机，允许你在项目历史中来回穿梭。此时，我们可以下载 NodeJS 8.1.1 的源代码。你不要忘记去点那个建议的大的蓝色按钮来下载一个项目的 ZIP 压缩包。对于我来说，为讲解的目的，我从命令行中下载并解压这个 ZIP 压缩包。但是，如果你更喜欢使用一个 GUI 工具，不用担心，你可以取代下面的命令方式：wget https://github.com/nodejs/node/archive/v8.1.1.zip unzip v8.1.1.zip cd node-8.1.1/ 下载一个 ZIP 包就可以，但是如果你希望“像个专家一样”，我建议你直接使用 git 工具去下载源代码。它一点也不复杂 — 并且如果你是第一次使用该工具，它将是一个很好的开端，你以后将经常用到它：# first ensure git is installed on your …