第九讲 GNU 命令行 TODO
Table of Contents
1 课前软件准备
- GNU 环境
- 课程与作业环境 macOS 上需要额外指定使用 GNU 命令
- gawk
- GNU awk 语言,数据驱动程序语言
- Alfred Aho, Peter Weinberger, and Brian Kernighan
- sed
- 文本流编辑器
- coreutils
- GNU 核心命令
- man-db
- 帮助文档阅读器
- info
- 层级帮助文档阅读器
- curl
- 网络请求和下载器
- bc
- 计算器
apt install gawk sed coreutils man-db info curl bc
2 拿来主义学习法
学习技能时,理论支持是辅助的,练习是核心的。在无法理解一个新概念时,最重要的是在练习中体验获得第一手经验。一个还不能透彻理解的工具,如果我会用,就已经掌握了它的重要接口部分。这与基础数学和物理课程的演绎风格很不一样,要求我们在不求甚解时,掌握工具之间关系的全貌,是“归纳”式的学习。这些内容的共同点是“恰好在物理实验的数据处理中有用”。此类经验性的技能,只要能以某种方式实现,满足四个原则即可,允许和鼓励“不求甚解”。归纳学习可以类比婴儿学习人类语言的过程。一开始,他所了解的概念都是分立的。随着他长大,联系才被慢慢建立起来。 这种想法与物理实验很像,因为只要涉及现实世界,就没有完整的模型。不论是光谱仪,还是量热计,其中总会残留无法解释的现象,被我们按照系统误差处理了。
3 命令行
命令行是指操作系统外壳中的命令交互界面,GNU 的环境里,特指 bash
。从 Python 的角度看,命令行是给它提供运行环境和基础的。从命令行本位看,它是所有文件和程序的出发点, Python 只是一种程序工具。
在 Git 和 Python 的学习中,我们已经不知不觉使用了 ls
, cd
, rm
, git
, less
, man
, cat
, pwd
等命令,用来帮助我们管理文件、运行 Python 脚本。在现实的任务中,复杂的逻辑要求程序之间的配合,而将程序可复现地协调起来正是由命令环境提供。中间数据的透明原则,由相应的文件查看命令保障。GNU 环境中管理数据处理流程的最佳工具,由灵活和高效远胜于各类云厂商提供的平台。
3.1 特点
命令行相比编译程序,非常易用,与 Python 的解释器所提供的 REPL 易用性一致,只要执行命令就有反馈。为了节省篇幅,我们把讨论集中到 bash
,即“GNU Bourne-Again SHell”,是最流行的命令行环境。只是与图形环境比,命令行的入门有门槛。实验数据的组织,都是文件的形式, bash
的文件操作非常自然。命令行是数据系统的“母语”,各类功能都是相应的命令接口。在命令行中,开发者与用户之间的界限变得模糊,用户更容易由自己的需求驱动成为新工具的开发者。打命令时,就是在创新,输入的命令变复杂,成了 bash
脚本,写脚本就进入了程序撰写的领域了。这非常重要,因为前沿的科学场景经常没有现成工业成品的支撑,学者需要在局部进行开发满足创新任务。易用性使命令行能满足实验的数据管理工具的开发需求。
“祖传代码”存在的一个原因,就是开发者与用户的距离太远了。用户无法逾越认知阻碍对程序进行维护和二次开发。命令行的工具中,“祖传代码”较少见。
bash
具有整合性和扩展性。任何语言写成的工具,最终都由命令行调用运行。 bash
命令协调运行 Python、R、C++ 等各类程序,因此它是最终整合所有工具的“胶水”。新的语言工具在不断涌现,它们都可以通过命令行协调在一起,命令行是变化中不变的部分。这种特性又反过来鼓励了工具减小功能的颗粒度,增大灵活度,从而相互组合出更丰富的新功能。标准的小工具把业务逻辑模块化,成为通用的成分,又进一步使得命令更具有可读性,更好地遵循复现原则。因此在命令行的包容下程序写得越短越容易理解,越容易写正确,也越灵活。不鼓励长的程序,与 Unix 工具设计哲学“do one thing, do it right”相符。
命令行的鲜明特点是自动性,可以把重复做的命令记录下来写成 bash
脚本重复使用。当脚本变得更复杂时,可以使用 Python、C++ 等语言重写,渐进演化。相比之下,图形界面的操作,很难记录重放。
命令行的普适性体现在,所有操作系统都提供命令的界面,大到超级计算机,小到智能手机、物联网设备,莫不如是。命令人机交互界面已经存在了 50 多年,即使计算机一直在变,一直有新的界面试图替代命令。这表明命令的设计有不朽的前瞻性,我们有信心预测它还会存在至少 50 年。
3.2 命令的类型
各类命令,可分成五种。一是可执行程序,一般由编译生成,例如 ls
由 C 语言编译成,放在 /bin/ls
路径下。二是可执行脚本,即解释型语言,例如 Python、Perl 的脚本。三是外壳内建命令,由 bash
提供,例如 cd
意为“change directory”。四是函数, bash
也做为编程环境,定义函数,重复使用。五是别名,例如把“ll”定义成“ls -l”的缩写形式,减化常用命令。
外壳 shell 在操作系统中,介于内核 kernel 和用户程序之间,广义上有命令行和图形界面两种形式,狭义上特指命令行界面,最广泛的例子是 bash
。通过 man bash
可得 bash
的简要说明, info bash
提供了 bash
的详细教程。
这种情况 上节课在结束的时候 我们说命令行里面 可以用的命令大概有5种 这种可执行的脚本 还有内建 还有函数以及别名 来上课了 一共有这5种 那么5种里边 我们可以看一下 这些常用的命令 都是什么类型的 可以用 type 这个命令来查看 比如说我们可以看 ls是什么类型的 我们可以看 我们看type ls 在我这里边 ls 这个是 ls 是 ls –color=tty 一个alias 就是别名 也就是说我每次打ls的时候 它都是带颜色的 我们看打ls就带颜色 然后如果我们 比如说type -a 它的意思是说 把所有的命令都找到 看它们是什么类型 比如说 type -a ls 我看到首先ls一个color的 别名 其次它是在这个bin里边的一个 一个binary的可执行的程序 我们看 如果我们直接执行可执行程序 它其实就没有颜色了 所以我们要有颜色 一般来说 就要给它加上color才行 而我希望每次都看到颜色 所以说 刚才是如果有别名的定义的话 我直接打ls 其实就 把它加上了颜色 在 shell里面的一种 定义命令的方式 也就是别名 那么其他的比如说cd 其实我们可以一直做 cd的 操作 就是改变当前的路径 就是这些操作 那么这些操作 我们可以看一下 cd是什么样的命令 它是shell的 builtin 也就是说是 shell程序里边的内建命令 cd 其实我们也可以看 type本身是什么命令 是吧 我可以打type来看 其他命令 我看一下type这种命令 然后看到type 其实也是 shell的内建命令 刚才我还打了ll是吧 我看一下这个ll是什么 比如说ll ll是 ls -lh 的一个别名 我不是说我这写的是 什么 -al这样 对你的别名是那样 我的别名是这样 是不是这样看一下man ls 什么alf a是all是吧 然后l是 l 在这 然后看F 大F是吧 那就是classify的意思 ls -alF S好 可以进行classify 大F是什么意思 看到了吧 我原来没打大F的时候 它就是这些名字 我打了大F之后 所有的目录后面都会加一个/ 表示它是目录 好 所以说在这个时候 我们不知道命令是什么的时候 就直接打一下type 就会知道 至少说这命令是怎么定义的 到底是在哪里定义 以及它定义是什么 接下来是shell里边比较 常用的一个工具 叫做管道 它的它的作用是把前一个程序的 标准输出 和后一个程序的标准输入连接 起来 它其实可以无限的连接 你可以连成很长很长 那么各每个命令 其实可以各司其职 也就是说 我们可以把各种小命令 通过管道把它组合起来 完成 大的功能 比如说在这里 我可以进行一次输出 比如说这些 我会进行一次输出 我不打感叹号了 感叹号有歧义 如果进行这样输出 它就会输出一段话 这一段话是输出到了 标准输出中 标准输出就是显示在屏幕上 那么我可以把标准输出 把它重定向给另一个程序 比如说另一个程序叫wc wc大家可能会觉得 它为什么起了这么一个奇怪的 名字 我看一下WC是什么意思 它应该是word count的 缩写 然后我们来数一下 比如说w -c来数一下 这个输出里边 到底有多少个字符 我们数一下28个 我看是不是28个 应该是28个 这样它就可以数出来这个字符 在这种情况下 如果加了感叹号 那么它就是29 我们看一下 比如说加一个 加一个句号 它是29 那加个省略号 它就是31 所以说 wc是用来数它的 个数 还有一个命令 比如说是seq他的意思是sequence 就是说sequence print a sequence of numbers 一种是只输出一个数 一种是歧视和每个数之间的增量 到停止 比如说seq5 那就是从1~5 从1~5 增量 增量是在哪呢 增量是在中间 从1~20 然后每个三个数 一个 就是1 4 7 10 13 16 19 这样的命令 其实就可以给我们在命令行 就可以生成很多序列 这些序列有时候会很有作用 比如说对文件进行编号 我们就可以在这里生成一个序列 对它进行编号 那么如果我们想对序列 进行一些过滤 比如说我想只取带7的数 我如果只取带7的数的话 那么 比如说seq30 有30个 我只取里边带7的数 这样 就有7 17 27 如果是再多一点 比如说到100 77 27 37 到 67 然后77也都有 这77 87 97 这个grep 我们一会儿可以看一下它的文档 它的意思是 取出 可以被7匹配的 这种字符串 因为本来seq100从1~100 然后取出7就取出了它 我感觉还是很长 比如说我想数一下 一共有多少个数字 因为取7了之后 它们每一个数字 都是占一个新的行 所以我就可以数一下 wc -l表示 表示lines 取这里边的行数 那么一共有19个 我想是不是有19 应该是有19是吧 因为有一个77 它是一个数 要不然是应该有20 如果我们不数行 比如说数这个数组 不是字符个数的话 它就是56 如果我这样说 如果这样数 我看到19 19 56 默认情况来说 我们可以看 看一下它的文档 它会告诉我们 默认情况输出的是 行数 这个单词数 和字符数 一共是三个量 所以我们在做 做这步操作的时候 这个就是行数 这个 单词数 这个就是字符数 那么刚才我们说 管道涉及到了输入和输出 可以把输入输出这样连起来 那么和它非常联系 非常紧密的概念 就是重定向 我们看到这个标准输入 就相当于连着键盘标准输出 就相当于连着屏幕 这两个 这两个标准的输入和输出 其实非常重要 它可以通过管道把它们都连起来 那么如果我们 希望不是把它 重定向到另一个命令 而是重定向一个文件 就可以用 大于号 表示是标准输出 重定向标准输出 那么在这种情况下呢 是把命令的输出 重定向的文件 比如说我们看一下 seq100 100的话 它就会输出100个数字 然后我把它们放到 这样一个文件里 s100 然后我们可以看一下 这个文件里面都有什么 比如说查看一下文件的内容 查看一下这个内容 我看这个内容还是很 我可以用less来看这个文件 内容 我们按一下上下的键 可以看到 一共有从1~100 这么多的数字 都输入到 输出到这个文件里 那么重定向的 比如说我还可以 用小于号比较直观 相当于 从s100 然后来把它输入进来 我说如果用wc的话来 数一下 s100文件里面都有哪些 一共有100个行 100个单词和292个 292个字符 这就是标准输入和输出的重定向 这里我们可以用-l来 只进行行数的测量 那么刚才我们简单地转了一圈 转了一圈试了几个命令 看到了管道还有重定向 我们大家会觉得 这些命令 很多 应该是很难一下子把它记住 那么这个时候在线的帮助 其实就显得非常重要了 比如说我忘了 wc到底是怎么用的 我就可以 man wc 就可以看到它的文档 可以前面有文档的说明 后面有 命令都可以用什么样的参数 最后还有 作者怎样来反馈这个问题 还有它的各种各样其他的信息 还有一些参考文献 那么用man的话 就可以来在线的查看一些文档 那么 对于这个shell命令 其实可以用help 还有help 比如说help 有时候可以用 help cd 这样就可以看到 比如说help cd它太长了 我用这个less 之前我们跟大家讲过 说用less 可以把很长的输出进行翻页 其实我们看 这个就是管道的意思 它help cd输出了很多的文字 然后我们把它 用管道把它作为 less的 输入 这样我们就可以进行翻页 来查看向上向下 我们看 cd 还有参数 比如说 L P 所以这些参数 其实我原来也不知道 第一次发现 cd还有参数 我们可以看在线的帮助文档 就可以了解cd是怎么用 这里边还有 关于cd的解释 那么很多命令 它约定了 自带一个help的参数 当启用 help的时候 它就可以打出一些帮助信息 比如说对于cat 就是忘了cat怎么用 cat –help 就可以看到这个 它的意思是说 concatenate 把文件连接起来 并且输出到标准输出 如果没有文件 文件的话 那就从这个标准输入 读入 然后它有这样的各种各样的参数 那么help 其实还有一种是cat -h 竟然没有 太可怕了 有些文件是有的 比如说ls 这个h 就不是help 那么大家用 两个减号的help 这里边有一个命令行参数的约定 这是GNU系统的约定 这个约定是说 如果我命令参数 只有一个字母的话 只有一个字母的时候 它用一个减号来表示这个参数 如果这个参数是一个单词的话 它用两个减号 来表示这个参数 我们在帮助文档里面 可以看到约定 大家可以不用去 那么不用去深究约定 但是一般来说你可能打错了 发现打一个单词的时候 你可能打一个减号的时候 就容易输错 这时候你打两个减号就可以 比如说help这是一个完整的词 所以它就是两个减号 好 那么接下来 我们其实已经 跟大家过了一下各种命令 大家可以来试验一下 下面的几个命令 你如果试验之后 你如果想深入了解 它是什么意思呢 可以看它的各种各样的帮助文档 有一个是man 来看它的帮助文档 比如说可以是 一种是help 然后还有 这三种形式大家可以 探索一下这4个命令 一个命令叫做 hostname 一个命令叫 uname 一个命令叫 id 我们来一起试验一下 hostname 它输出 就是大家系统的名字 有各种各样编号的名字 不一定是你起的名字 但我这个系统是我起的名字 然后比如说 uname是 返回这个系统 是什么样的系统 uname -a是 把系统的所有信息都输出来 比如说我这个系统是一个 这个Debian 然后它的内核是这样的 它是在这一天 生成出来的 然后后边是系统的结构 这个系统CPU的指令集 下一个是ID ID 是说我当前用户的 当前用户的特性 比如说我现在用户名是这个 用户的组织 然后一共还有其他的组 可以使用 Cd 音频视频什么的 大家可以打一下id 可以看你 当前用户都在哪些组里边 也可以别的 id -u id -g就有各种各样的命令 大家可以通过 man id 来查看它的这些 这些个用法 然后还有date 就是给出当前的时间 现在是 CST中国时间 北京时间 下午3:03 那么date其实它有 也有各种各样的参数 比如说date –help 我们发现help还是很长 还可以定义 我们输出的时间的一些格式 在我们日常的数据 处理的时候 其实还是非常有用的 因为我们说采到一个数据 我们可以用date 直接把它的格式一起 把它的日期一起输出出来 那么还有其他的一些工具 比如说uptime 大家会继续探索这些命令 比如说uptime是说系统的 到目前为止启动的时间 我机器已经开了一天了 一共有10个用户 在这个机器上 目前的使用情况 然后 dmesg是 显示 应该是可能要sudo 这个dmesg是显示你现在的 内核的输出信息 然后如果太长的话 你可以用less看一下 然后对于我的这里面会 告诉我那时候开始启动的时候 看到了什么 看到了什么样的硬件 对于Windows下面 WSL可能会 输出的比较简洁 好 我们下课休息 咱们继续上课 我刚才课下有同学问说 alias 怎样定义 alias就是别名 有的时候 我们要打太多的参数 比如说每次 都打ls –color的话 感觉太麻烦 我每次都ls –color -l 然后我想让它 让我打的快捷一点 然后就可以这样的定义 alias alias ls就等于 ls –color 默认的定义 应该就是这样的 如果你打ls 它带颜色的话 应该你的系统里面 有这样的一个别名 比如说我觉得 hostname 感觉好长 要打8个字母 才能执行命令 我希望能够只打两个字母 就执行这个命令 hostname 这样的话打HN的时候 就执行了hostname 这种做法如果你发现 一直都在打一个很长的命令 就可以通过这样来简化 这是简化的第一步 但是还有一个问题 比如说 我这样定义了hostname 之后 我把这个关了 这些都关了 关了之后 我又重新打开了一个 打开了一个窗口 这个时候再打HN就没有了 消失了 我就需要重新定义 HN=hostname 这样HN就有了 这样重新定义 这也是我一直在跟自己重复 这不是不符合我们的一次的原则 所以说我们看一下 在你的 home目录下 比如说 在你的home目录下 你的home目录下 会有一个 .bashrc这样一个文件 bash就是我们 刚才说的 Bourne Again SHell 这个shell shell的名字 rc其实是resources的缩写 也就是说bash里边的资源 比如说我看一下 .bashrc 这里面就有一些 我现在这个环境里面 它默认的一些变量一些定义 对 像我的是这样的定义 你的可能也是别样的定义 比如说我这个定义里边 就有 ls –color
4 第二段
你的可能是别样的定义 比如说我这个定义里面 就有 ls color 连grep也默认有 可以有color 那么如果我想把 HN加进去 就可以在这里改 alias hn=hostname 这样一个文件 是每次打开一个shell的时候 它都会自动的执行 所以说每次都执行 文件里边的 这些命令 那么这些命令被执行了之后 如果每次 alias的别名的定义 这样打开一个新的环境 它都有别名存在 大家可以看一下 我的别名系统 它其实还是 而不是别人系统 初始化 相当于resource 但我自己的resource系统还是挺复杂的 给大家来看一下 它里面有各种条件判断 这些判断 然后有很多这些别名 除了这些别名 还有很多变量的定义 除了变量的定义 还有一些 shell里面的函数定义 这都是经年累月 大家现在不用写那么长 这些都是经年累月 有的时候觉得 这个工具很有用 就加到初始化这个文件里面 那个东西很有用 还是可以加进来 加进来之后可能时间长了 它就太长了 变慢了 你可能再重新的整理一下 这是一个 可以自定义自己环境的过程 比如说自定义用别名来 定义你的命令的缩写 好 我们回来 大家有没有把这些命令 都试着做一遍 还有几个命令 比如说find find是 比如说是在当前目录下 找所有带html结尾的 文件 在各位同学的目录里面 可能没有这个文件 你直接find这个.就可以了 find 点就是说 找出当前目录下的所有文件 比如说find . 文件太多了 找一个文件少一点的路径 我到这个homework里 homework里面也会很多 就是说 到TOLA里边 偷懒里面有这么多 有没有少一点 到data里面就少一点 比如 find . 就可以把所有的 所有的这些文件输出出来 那么我还可以在这里后面加一些 加一些参数 大家注意这个参数 其实不符合我刚才说的命名原则 这个参数虽然是一个单词 但它前面只有一个 一个- 这都是历史的原因 它没有跟标准靠拢 这就是用了习惯了 都记住了 比如说 就是所有的CSV文件 都把它找出来 如果是用png 所有的png文件找出来 比如说所有以c打头的文件 find其实有非常丰富的 其实有非常丰富的 这个格式了 只要看它的文档 就有非常的长 就很长 还有各种各样的格式 如果能掌握它的话 其实可以 非常强大的使用 在这里我们只是给大家 看一下 感兴趣的同学 可以深入的去挖掘命令 那么之前我们还遇到了file命令 file是来简要的输出一下文件的信息 比如说我想看ls是一个 什么文件 刚才我们最开始我们看了 type -a ls 它最开始是一个别名 但是别名之后的 ls 其实是指向了 文件系统里边的一个 编译好的文件 编译好的文件 我们看一下 它是什么样的 它是一个什么什么格式的 一个可执行的程序 这个程序的指令集是 amd64位的 它这个程序的格式是什么样 这有各种各样的信息 比如说我们再看一下 CSV文件 它是说CSV文件 是一个 Unicode的编码的 纯文本 看看这里边是不是有 是不是有国际语言 然后看一下 对这里面有很多汉语 有很多汉语 所以说它就会告诉我们 它是用户编码的文件 大家不用找 跟我一样的文件 在你的路径里边 肯定有各种各样的文件 我可以看各种各样的东西就是 它是一个图形文件 比如说 unison.log.gpg 它是一个数据文件 接下来大概可以试验这些内容 比如说touch touch是改变文件的时间 最后修改的时间 那么如果这个文件 不存在 你touch的时候 它就会多出来这个文件 比如说 在我们现在路径里边 我看这个路径里面 一共有这些个文件 这些文件我看这有个s100 比如说我touch s101的话 我在进行当前 文件查看 它就多了一个s101 如果我看它修改时间 比如说s100 是我刚才修改的 是2点54修改的 那么如果对它进行touch 它的修改时间 就变成了3:30 就相当于把这个文件 假装把它改一下 这样的时间 最后修改时间 就变了 还有一个是echo 输出一个信息 不管是什么东西 对 比如说可以这样输出信息 我们看了一遍 这些各种各样的命令 这些命令五花八门 各种各样用途都有 这些命令肯定都是 冰山的一角 各种各样的命令 其实都是 存在的 大家不用每次都把它记住 只要用的时候 能够知道 大概有这样的命令 能够找到 就可以 同学们有什么问题吗 没有问题是吧 没有问题我们做类似的练习 比如说我们 seq 比如说9 然后我们如果把它 输出到就是s9 这样 它就输出到 s9的文件里 大家有没有安装 csvkit 这个是可以在命令行里面 查看CSV文件 然后其中这里面就有一个命令 叫做csvlook 然后csvlook我们看 S9 它就给我们做成了一个表格 1是一个标题 它是认为这是我们一个标题 比如说标题这个叫 这个叫数字 我把seq里面加个标题 或者我们这么加标题 这里边没有head 我就这样 echo 数字 这样 这样s9里边的第一行 就是数字了 是吧 然后我再让把9个数放进去 注意这个地方 我重定向的时候 用2个大于号 表示说 它不把这个文件 覆盖 在这个文件后边 追上这几个 s9 然后看csvlook 这个汉字不是很好 看起来 它应该没有考虑到汉字的情况 我们这样打 然后重新来 这样把number输进去 然后输出出9个数 两个大于号 然后我们看 其实它是每行一个数字 它相当于一个CSV文件 然后进行csvlook 它对于英文的字符 还是比较友好 可以看出来 把它拍成了一个表格 你可以看你的大作业里边 可能有csv文件 或者是其他地方找的csv文件 比如说TOLA的这里边 你要没有TOLA也没问题 你再看别的CSV文件 比如说TOLA里面 这个stations 然后就看到 原来 stations是这样 是这样一个CSV的文件 它里面有这个标题 和每一行的数据 都是用逗号隔开的 然后如果对它进行 csvlook 所以它就会把它汇集成一个 一个看起来比较容易理解的 表格了 这是 一套工具 大家在读csv的时候 可以使用 它里面还有其他的 比如cvsjson看起来 可以把csv转成json 它竟然没有帮助 这样可以看到它的帮助 所以说 对于我也对这个工具不是很熟悉 但是我们可以看到 在命令行里面 我们能够发现工具的各种功能 比如 csvlook 看看一下都有什么样的 参数 还有各种各样这些参数 所以说大家在查看中间 结果是CSV的时候 就可以考虑用命令来查看 好 刚才我们探索了 这些很多个命令 它们每个命令 都有各自的用途 这些各自的用途 大家一次没有记住 也没有关系 你可以拿着一个 cheat sheet 或者是拿着一个教程 然后你想用什么的时候 就找出来用一下 然后如果你未来的一段时间 你还会用到它的话 你就慢慢的把它记住了 这就像背英文单词一样 然后你如果未来一段时间 你没有用到它 你忘了 也没有什么问题 接下来是通配符 通配符是对文件操作很重要的 一个模式 规则匹配的一些通用的字符 这里边shell里面 比较特别的字符 一个是* 一个是? 开始讲过说 命令行是对文件操作非常亲切的 一个环境 而文件 又是数据的基本的载体 所以说我们这些通配符 就体现了这一点 比如说我现在的路径里面 就有很多的文件 还是到我的 home目录里面 这里边有很多的文件 嗯比如说这些文件 大家可以自己来 看 你的home目录里面都有哪些文件 比如说这些文件里 有M打头的M开头的 我只要看 比如说echo m* 那么这个* 它代表的是任意一个字 包括0的字符 任意字符 匹配的是当前的文件夹里的文件 比如说这里边有这么多文件 我如果打m*的话 那么这两个文件夹 movie和music就被匹配了 比如说我想匹配所有的 以log结尾的文件 我们就看到了是这样的 log文件 这是* ?呢 它可以替代一个字符 不管这一个字符是什么 比如说m 4个字符我都不知道 比如说m 我不知道这4个字符 都是什么 我看一下 m 4个字符 它可能匹配成movie music 我也可以用路径来进行这些匹配 比如说 在这个路径里面 usr doc 比如说我想看所有的 以core打头的 开头的这些路径 就是说 它就能够输出出来 匹配出来core打头的一个路径 我们可以看一下 这个路径是什么 然后我们如果想 看 比如说看路径 下面的所有 gz结尾的文件 这个是一个压缩的文件 那么它就可以 输出所有这些文件的路径 我也可以用 ls 来列出这些所有的文件 那么这些是我们在探索一个 目录结构的时候 常用的一些操作 比如说我想探索一下 所有 所有以一个字母加z 结尾的文件 这样 比如说我这些share 假如说忘了 我就这样把它换成问号 这都可以匹配出来 这都可以匹配出来 所以说通配符就是可以 以一定规则 把某些文件给它找出来 那么比如说在我的路径里边 如果有很多之前的讲义的话 那么就有都是以Python开头的 有一个短线 短线后面是接着一个命令 那么你对它进行匹配的话 就可以把以前的这些东西 都匹配出来 那么比如说ipynb 是 那一共有这些文件的话 那么如果我们 来进行这样的匹配 这是一个文件名后边 我也不知道是什么 这么 这样加进去 也就把所有文件匹配出来 好 关于匹配大家有什么问题吗 匹配起来 其实它的功能不是特别强大 是吧 我们只能做简单的替换 有的时候 我们想做一些更加高等的操作 比如说 我想做一些 这些匹配的做不出来的 一些操作啊 这个时候 用到一个 非常强大的工具 这也是我们课程中 第一次遇到 所谓的这种形式语言的例子 那么接下来我们会跟大家讲一下 字符串的匹配和正则表达式 之前我们在python里面 其实已经做了一点初步的字符串 匹配 比如说 那些以什么开头的字符串 或者以什么结尾的字符串 或者是包含什么字符串 今天我们也用了一点 比如说刚才我们所做的 grep 从1~100个数取其中带7的 那么它就把 所有带7的这种数字 把它匹配下来 那么如果我要做更加复杂的匹配 比如说我们要处理文本 或者是处理一些其他的数据的 输出 那么正则表达式 就是一个非常强大的工具 它为什么强大呢 首先正则表达式是一种形式语言 形式语言的意思 是说这个语言可以精确的用数学 和可以处理的公式 定义出来 比如说python严格来讲 它也是可以用数学 把它的语法描述出来 然后可以用机器把它处理 那么它也算是一种 很复杂的形式语言 而正则表达式算是相对来讲 很简单的一种 形式语言 或者说我们可以把它 说成是公理语言 比如说我们自然语言 平时说的汉语 就没办法公理化 但是这种语言 我们如果把它可以公理化 它就有一个非常好的好处 公理化了之后 就可以用机器来自动的处理 而且公理化之后 它的使用角度的好处就更好 既然它可以公理化 它可以通过工业标准 来严格的把它定义下来 那么用户和语言的引擎的开发者 就可以完全分工协作 比如说我作为用户 我只知道 说这套语言就可以 然后开发者 它可以开发出来 非常强大的语言的 这种语言的实现 那么就我就可以使用 非常高性能的一种事项 比如说语言的基本的要素 这个点 是代表任意的字符 比如说刚才的例子 seq 我现在是找里边的7 找7的时候 这里边第二位是7的 有第一位是7的 我希望只找第二位是7的情况 那么我就用打一个 .7 我应该不加引号 也是可以的 所以这样点 就代表一个任意的字符 比如说我想找第一位是3的 从30~39 但是点表示是一个字符 比如说我1000的话 1000可能有点害怕 1000有点爆炸 试一下 所有带3的 都被它这样匹配下来了 比如说1000 我如果看1000的话 那就所有的 带3的都被它找出来 但是第一位是3的这种 最后一位是3的 应该就没有被找出来 但是我希望开头是3 你看一下 刚才的这些要素 就是说开始的部分 是 表示开始 ^表示开始 $符号表示结束 然后*表示任意次的重复 大家手里边的之前发的那个 小抄里面 有它的各种要素 大家可以参考的看一下 目前来说 这些定义还都比较抽象 因为它们是从 把数学公理 把它定义出来 但是目前为止 我们先在shell 加号 然后问号 编号 还有编号 每个编号还有点 进行一些练习 它们都可以通过公理体系 定义出来 定义出来之后 比如说我们想做一件事情 想找出开头是3 开头是3的这种 这种数 我看就把它过滤了 就只剩下开头是3 接下来有一个数字 如果我让它说开头是3 然后中间是某一个数字 结尾 然后就到了结尾 不让它 有两位数字 或者多几位数字 不让它有两个数字 或多几个数字 这样就可以把它 过滤 我们是从满足这个条件的数字 就开头是3 之后有一个时间的数字 那么如果是*的意思 就是说 星号的意思 这个表示是开头 这个表示是结尾 这表示任意 然后* *的是0 到无穷 然后都可以 比如说我在这里打个星号 意思是说 在3的后面跟了一个 跟着某一个字符 这个字符可以任意的字符 可以重复 任意多遍 也就是相当于 它可以匹配3. 3.. 3... 都可以 所以我这样打出来 所有3开头的 比如说 3开头的 它重复0次是3 重复一次 是两位数的30大头 重复两次 那就是三位数300开头 是吧 那么如果是加号呢 加号是 至少重复一次 来重复多次 也都没问题 加上20 至少重复一次 把它变成加号 发生了什么 遇到了一个坑 加号 不再grep里面 要用加号的时候 我们需要用egrep才行 加号的时候 需要使用egrep 加号的时候表示 它重复一遍 到无穷遍都可以 但是这个语法 我们可以看到 这是一个公理体系 从一开始 它可能有一个非常 非常基本的语法 然后随着时间的发展 大家觉得可能需要更多的元素 它可能就会加各种各样新的标准 比如说最基本的叫作 basic 基本正则表达式 然后加了一些扩展的 比如说扩展的这么一个表达式 然后有时候发现扩展的也不够 它就会在扩展成为叫做perl 扩展的正则表达式 比如说现在我们看到加号 它在基本的正则表达式里边 没有被定义 它就是一个普通的加号 并没有一些特殊的意义 那么所以我们就要用扩展 这种正则表达式 所以我们打一个e e是它的一个别名 应该 比如说我们可以看一下 egrep是啥意思 egrep是在这里定义的 我们可以看一下egrep是什么 egrep是一个一个脚本 在这里定义了一个脚本 我们那么回到刚才的 正则表达式里面 这个的意思是说 在3后边接任意一个数 这个任意数至少出现一遍 那么 那也就是说单独一个三 它就会出现了第一个三 至少出现一遍的 之后是 加号 这里边的问号 大家注意 这里边的* 跟刚才说的文件匹配的* 那意义是不一样的 这一点比较容易搞混 大家要注意 而这里边的问号 和刚才文件匹配的问号 也是不一样的 因为这里边的这些符号 都是 从一个规则演化出来 问号的意思 是说 要么是 04要么是14 这个意思 所以说我们可以把这个点 变成一个问号 问号之后我们看 它就是0次也可以 比如说3之后 0次什么都没有 然后30后边有一次匹配 比如说我们 比如说23问号 如果是这种情况 会出现什么呢 它可能或者输出一个 或者输出一个2 后面有个3 这样 对问号前面跟着 比如说我输出 输出多一点 然后我只找这种 第一个数是2 第二个数是3 第二数有任意多个3的 这种情况 我看 比如23 233 2333 23333 是什么的倍数 它不是 它匹配的还不是这种 计算 它还都是文本 文本匹配 这些都是文本匹配的 好 这些是几个基本开头结尾 还有这种 如果我不要求结尾 那就是各种 不要求结尾 可能就会比较乱了 所以各种23开头的都有 要求结尾可以把它限制住 然后现在我们可能会 这些基本的 我们可以做一些小练习 比如说刚才我想到的23练习 还可以 还可以有一些别的 我们可以怎么写 比如说 有没有2都无所谓的 有各种各样的是吧 那么大家就可以想一下 那是就可以过滤出任何你想要的 这种 这种字母 这种字符串 那么比如说括号是组合的意思 比如说我希望 比如我希望23作为一个单位 把它组合一下 让它开头让它结尾 好 这样就是23为组合 然后星号它可能重复 零次一次或者是多次 这样就可以把它进行组合 比如说我是+ 它就至少得出现一次 也是这样 比如说我可以让3 或者不出现 它就变成了 2也是匹配这种情况了 然后22也是23 也是 比如说这种情况 首先是在grep里面 或者有2 必须得有二开头 然后3或者出现或者不出现 然后后边这种东西出现多次啊 最后是结尾没有别的 那么这些数据是什么呢 每次有一个2 后边就可以跟3 如果3结束了 就必须得有一个新的2才可以 跟新的3 是吧 人类的语言是苍白的 那么在正则表达式里面 我们可以做出各种各样的 各种各样匹配的规则来 而这个规则 因为它可以公理化 所以说做这个理论计算机的这些 研究人员 或者是程序 写程序的这种高手 它可以对着公理体系优化的 非常的 效率优化的非常高 使得我们过滤一些 字符串 可以让它有非常高的效率 这样只要我们可以把我们想要 做的事情 描述成正则表达式 我们就可以站在巨人的肩膀上 我们就不用自己来 写一个规则 来寻找这种字符串 如果我们可以把它描述成 这种正则表达式的话 我看一下一些其他的 扩展的符号 比如说这个是或 或 那么这个地方 我们可以是或者跟一个3 或者跟一个4 3或者4 那就是23或者24 或者2323 或者2324 2423 可以这样简洁的表达出来 但是我用语言来表达的话 人类语言表达就比较麻烦了 比如说4可以是可选 那么各种情况都 都可以有 是吧 方括号是可以选一定的字符集 比如说 我想从3~9都找出来 但我就要写3456789 这样写出来就很难受 写的比较多 比如34567 然后到7的话 那就是23235627 然后它们都可以这样子 这样写我感觉不是 很好 我可以用中括号 设定它的一这样一个范围 [3~7] 它就是代表了 第一个数是2 第二个数是3~7里边的某一个数字 然后这样的两个数 它们可能有一定的重复 比如说这和刚才是一样的 那么这个字符集 不仅可以数数 也可以数这些字母 [a~z]这样 比如说 我用这个生成一个随机的字母 大家可能没这个命令 那么比如说我们输出 firefox 23456 就是这样 这时候我们比如[a-z]我们就 可以说这样 [a-z]然后空格 它就匹配了 比如说x就在[a-z]里面 然后它是空格有一个二 比如说 1~5 1~5 那也是可以匹配的 因为这里边有1个x 这里边有一个2 它们都可以被这个范围所匹配 进去 但是比如说6~9 那就无法匹配了 所以说这套语言 我们看这套语言 其实非常简洁 一共就这几种 这几种字符一个点 一个^ 一个$ 一个* 一个+ 一个? 一对括号一个竖线 然后一个中括号 基本上就 表现力其实就非常强 很多我们日常的 这种 自然的情况的处理 都可以用 这些表达出来 最后比如说我们想说 这个字符范围里面 不包括a 不包括abc 就可以用一个 这里边和这个不一样 就是在中括号里面&表示取反 比如说 它不包括abc 不包括abc 不包括ax就匹配不了 这个数字这样可以匹配 不包括ax 就匹配不了了 就把a和x除去了 那么这个x就没办法匹配 那么不包括abc 它就可以匹配 不包括a到z 它就匹配不了了 因为x在里面 如果a到w 那么x就 可以匹配到 这个上面 然后1~5 可以匹配到这个上面 这样的一个字符串就可以 可以了 大家有什么问题吗 你要把它去掉 你可以这样 让它必须在开头 然后就匹配不上了 ^在这儿 所以说 我们一下子学了一门语言 这门语言里面全是这样的符号 这堆符号我们在想的时候 其实比较容易构造 我们可以写出来一堆这种 这种奇奇怪怪的符号这样 但是别人来读符号的时候 就可能会比较困难 但是我们构造的时候 比较容易 这个是我错的 这个是对的 好 大家可以体会一下 然后我们下节课 继续来讲 正则表达式 刚才场外听众 给我纠正了一下 场外听众 他是形式语言与自动机专业的 所以说 他讲了说公理语言表述是不对的 所以大家请听 把它划掉 你们的场外听众它们都在看 在看直播 我到时候把改一下 公理语言是不对的 就叫形式语言 形式语言就可以 理解为 从做一些基本的语言元素的假设 在假设基础上 演化出来一套语言 相当于语言有一个 形式化的定义 那么这个形式化定义 就使得我们可以通过一些数学的 结构 来描述语言 有这个结构 我们就可以通过机械程序的 来对语言进行处理和匹配 好 刚才关于正则表达式 大家有什么问题 没有问题是吧 好 还有一些扩展的语法 我再讲一个扩展语法 这里边我临时想到了 我们可以把它 就直接把这个范围写出来 比如说M这样写出来 它就是代表着 可以从M到N的重复性 给大家表示出来 比如说我们刚才那个例子 比如说 我让23 只有1~2 三个是不行的 大括号 有1~2 那就是说1 2 有三种 就是123 是吧 如果是0~2 就是 0 1和2 所以这个也比较直观 但是大家不一定能够一下子记 这么多 这些没关系 大家只要见过就可以 想到的时候再查都没问题 因为我们给大家发了 各种各样的备忘录 备忘小抄 用的多了自然就记住 如果你一直 一直没有使用的话 说明它不重要 忘了也就忘了 那就没什么问题 好 那么关于这个 正则表达式 我们来做一个作业 发布了 我们来做一个正则表达式的作业 做作业之前 我想到了一点 没有跟大家讲 就正则表达式 是非常普遍的一个形式语言 形式语言 无论从理论上 还是实践上 都有非常大的应用和它的意义 比如说 python里边 你也可以使用正则表达式 比如说python 我们如果搜索python Regular Expression 你就可以看到 python的正则表达式 一般会缩写成regex 这样的缩写 我们可以看到Regular expression operation 这是python也支持的 在这里可以看到这个文档 这里边是python的定义 这个点 开头和结尾 然后* + ? 还有python里面又定义了一些别的 比如说*? +?和?? 这些是python它的扩展 然后 {m} 是恰好重复m次 {m-n}是恰好重复m到n次 然后问号 这个问号是贪心的 不贪心的问号 这个或许会用到 但是大家要注意 只有这些比较基本的定义是 每种工具都共有的 但是其他的一些扩展 可能各个工具 有一些细小的区别 当我们在用的时候要试验一下 然后在这个工具里面 多看一下它的文档 还有一点是 反斜杠 从左上到到右下的形状 这个斜杠是取消这些特殊字符的 意义 因为刚才没有同学问这个问题 同学们可能会问说 我就想匹配美元符号本身的 怎么办 这个时候你 你把 \$ 它就匹配了美元符号本身 它就失去了结尾的意义 比如说我想匹配本身 大家在用的时候多体会一下 多试一试 然后还有一些其他的扩展 这些其他的扩展 感兴趣的同学 可以来看一下 Python其实加了很多种 扩展 这些扩展 有些时候都非常实用 我们看一下作业 我们来做一个 做一个今天的作业 好 这个作业 发群里一个 你们加群是吧 然后我们看一下作业 我们的作业都非常的有创意 然后我看的都觉得好玩 因为是公众号 因为物理系强大 我用python做作业不行吗 不行是吧 你明天再不限制于 lst 这么大 这都是什么语言 这个作业太好玩了 虚拟机 你用虚拟机里边 也应该带了输入法 比如说输入法 我知道输入法有这三种 可以看到 你可以从网页上拷贝下来 然后贴进去 应该是可以贴进去 可以贴 那第一个跟第三个 西北大学 河北大学 台北大学 北大西洋冷暖流 太神奇了 怎么了 你的是什么 WSL环境吗 怎么办 这里边有一点 我没有跟大家讲 shell的脚本 如果我们做这些输出的话 我们先来给大家补一下 shell脚本 比如说我要想这样输出三行 123的话 那么 我每次都打这三个命令 感觉很累 我希望把它放到一个文件里边 然后我能多次执行 就像刚才的bashrc 一样 我可以自己先找一个 创建一个文件 比如说是 123.sh 这个.sh表示 shell的脚本 让 sh里面 就记录下来 我要执行的命令 比如说像我刚才的 随便两个命令都可以说 这样 这样我就有了123.sh 我没存吗 比如说我创建了一个这样的文件 创建了一个这样的文件 放在这个文件 我看到 这个文件的内容就是 然后我如果用 用bash来执行这个文件 就可以直接把这个文件输进去 它执行了 我记录下来的这些命令 直接就执行 一般的shell应该也可以 这里边我们统一用bash 这样 在作业里面 要求大家把你的打的命令 记录下来 其实就是记录在这样一个文件 里面 让它输出这些 让它输出这些统计得来的个数 然后 就可以做那个作业 作为你的结果 大家可以继续做