Regular Expression
Regular Expressions
-
POSIX Basic Regular Expression
- grep
-
POSIX Extended Regular Expression
- egrep
- awk
- emacs
GNU Extensions
Shorthand Classes
| shorthand | equivalence |
|---|---|
\w |
[[:alnum:]_] |
\W |
[^[:alnum:]_] |
\s |
[[:space:]] |
\S |
[^[:space:]] |
Word Boundaries
| shorthand | matches |
|---|---|
\b |
position at a word boundary |
\B |
position not at a word boundary |
\< |
position at the start of a word |
\> |
position at the end of a word |
\` (backtick) |
position at the start of subject string |
\' (single quote) |
position at the end of subject string |
Perl Compatiable Regular Expression (PCRE)
grep multiline mode
-P: 使用 Perl 正则表达式扩展-z: 让 grep 把输入的行看成是一个多个行的集合,一个整体.*?: 后面的?表示.*按 non-greedy 模式匹配,也就是尽可能少(短)的匹配(?s): 让.匹配包括\n在内的任意字符,也就是所谓的 dot all flag.
rg multiline mode
-
-U, --multiline使能多行匹配,允许正则表达式里包含\n(普通模式下不允许),但-U并不会改变.的语义,所以你仍然需要显式地给.指定(?s)flagrg -U 'struct file_operations .*? = ?\{(?s).*?\.mmap = (?s).*?\};' -tc drivers/gpu
这个例子找出内核 GPU 驱动中所有重写了mmapfile operation 方法的c文件
Lookarounds: Lookahead, Lookbehind
| 语法 | 名称 | 含义 |
|---|---|---|
| (?=foo) | 正向先行断言 Positive Lookahead | 向前(右) 字符串里必须有 foo |
| (?!foo) | 负向先行断言 Negative Lookahead | 向前(右) 字符串里不能有 foo |
| (?<=foo) | 正向后行断言 Positive Lookbehind | 向后(左) 字符串里必须有 foo |
| (?<!foo) | 负向后行断言 Negative Lookbehind | 向后(左) 字符串里不能有 foo |
- 它们只是检查是否匹配,不作为最终匹配结果的一部分,即所谓"断言"
- 它们可以解决 Non greedy 匹配有时解决不了的问题
rg(ripgrep) 默认不支持 lookahead, lookbehind, 需要加-P或--pcre2选项
Advanced Shell
基础知识 - 变量和函数
Linux 下的 Shell 有很多, sh, bash, csh, zsh 等, 这里主要记录一下 bash 和 zsh 的一些不同之处
特殊变量
$!最后一个后台命令的 PID(glmark2 & PID=$!; echo "PID: $PID")- 在子 Shell 中启动 glmark2, 并打印 glmark2 进程的 PID
(...)用来在新的子 Shell 里执行命令
Parameter Expansion
Use an alternate value
1 | ${var:+WORD} |
如果 var 没有设置或为空,则这个变量展开为 Nothing (注意:不是空 empty, 是 nothing), 如果被设置了(不包括被设置成空),它展开为 + 后面的 WORD.
如果冒号被省略,则 var 即使被设置为空,它也展开为 + 后面的 WORD
Indirect
1 | ${!var} |
如果 var 的值是 MESA_DEBUG, 那么这个形式展开后是变量 MESA_DEBUG 的值,例如 export MESA_DEBUG=1, var=MESA_DEBUG, 则最后的展开结果是 1
Quoted
1 | ${var@Q} |
带 @Q 指变量展开后的值被单引号引起来,例如 export ABC=abc, echo "ABC=${ABC@Q}" 的结果是 ABC='abc'
反斜杠 backslash \
\ 在 shell 中是用来转义字符的,就是说 echo "\\\\" 显示的实际只有一个 \, 而且 while read var 时要注意加 -r 选项,读入原始字串
经典命令
exec
exec 命令有 2 个特点:
- 直接覆盖当前进程,就是说进程 PID 不变,但执行的代码被更换了
- 原来的 shell 环境被销毁,这样当前的代码结束后,也就不会返回原 shell(没得返回), 直接退出, 所以循环中慎用 exec
- 可以把它想像成系统调用
execve()
下面是 linux kernel 安装 bzImage 的一段代码,其中就使用了 exec, 保证列出的 4 个安装脚本中,只执行第 1 个存在的,不会重复安装
1 | # User/arch may have a custom install script |
timeout
timeout 命令用来给一个 COMMAND 设定一个 DURATION, 这在自动化中很有用,比如
1 | for i in `fd --type x`; do timeout -k 0.1 10 ./$i; done |
假如当前在 VulkanExamples 的 bin 目录下,上面的命令表示让每个 demo 执行 10s 后结束(timeout 给它发 TERM 信号), 如果发了 TERM 信号后,又经过 0.1s (-k 0.1),这个 demo 还未能退出,就再发 KILL 信号,强制结束它
tree
tree 像一个简单的文件浏览器,但它并不是 shell 内置的命令,apt install tree 或 pacman -S tree 都可以安装。有时一个目录中包含太多的文件,tree 的默认输出就不太好浏览,这时可以只打印目录,并限制搜索深度
1 | tree -L 2 -d |
crontab
crontab -e (添加定时任务), 不光可以添加周期性的定时任务,也可以添加开机时一次性任务
1 | @reboot /home/luc/mystart.sh |
crontab 是每用户的, 就是说当前用户设定的任务,只有当前用户的权限,所以如果有些情况下任务执行需要 root 权限,就需要切换到 root 用户后 crontab -e
文本处理 - awk, sed, grep(rg) 三剑客
Linux 下的文本处理三剑客: grep, sed, awk, 除了它们其实还有一些小巧的命令,如 tr, cut 也可以帮助我们快速处理和格式化文本。
下面以一个例子为例。
awk
1 | awk 'program' inputfile1 inputfile2 ... |
awk 的调用形式就是上面这样的,而其中的 program 由若干条 rules 组成,而一条 rule 由一个 pattern 和一个 action 组成
1 | pattern { action } |
awk '{$1=$1};1'- 将一个字段前后的空白(空格和 Tab) 全部清除
sed
sed 和 awk 一样,都是按行处理文本的。
sed -n '2 {s/^/#/; p; q}' file- sed 默认会将每一行都打印出来,
-n取消这一行为 - sed 可以在操作的前面指定位置和范围, 如
- 行号
- 正则表达式
/^foo/ - 两个正则表达式锁定范围
/^foo/, /bar$/
- 如果
-n后,完全都不打印了,但如果又想将处理后的行打印出来,使用p命令 q命令的作用是立即退出,sed 的默认行为是对第2行处理完后,虽然后面的行都不需要处理,但 sed 仍然会继续将后面的每行往模式空间加载。
- sed 默认会将每一行都打印出来,
grep/ripgrep
-
在 Linux 内核源码目录下,搜索
drivers/gpu/drm下所有的DRIVER_NAME定义,并排序后格式化输出1
2
3
4rg '#define DRIVER_NAME' drivers/gpu/drm --no-heading \
| tr -s '\t' | tr '\t' ' ' | tr -s ' ' \
| awk -F':' '{printf("%-52s%-40s\n",$1,$2)}' \
| sort -k4rg(ripgrep) 比 grep 更快,更强大tr在不带任何选项时,默认执行替换,例子是中将 tab 替换成 空格,-s表示squeeze-repeats, 就是去掉重复的字符,例如多个空格只保留一个awk天生支持 C-Style printf
-
rg '\[package\]' -ttoml --glob '!Cargo.lock'- 在一个 rust 项目顶层目录,只搜索 .toml 文件中的
[package], 而忽略所有 Cargo.lock 文件
- 在一个 rust 项目顶层目录,只搜索 .toml 文件中的
引号
当混合使用 awk 和 sed 时,比较便利地处理引号的方法是定义 awk 变量 -v Q="'"
- awk 的
printf()函数第一个参数必须使用双引号printf("%s: %s%d%s\n", $1, Q, $2, Q)- awk 中的用户自定义变量和内置变量,使用时都不需要加
$, 如NR,NF
- awk 中的用户自定义变量和内置变量,使用时都不需要加
- awk 和 sed 的命令字串必须用引号括起来,当用 awk 生成 sed 命令时,将单引号定义为 awk 变量尤其方便,可读性也强
行范围 (Line range)
sed, awk 都支持行范围,如 sed -n '3,5p', awk 'NR >= 3 && NR <= 5',它们的效果是一样的,都是只打印给定文件的 3 到 5 行, 除了行号, sed, awk 还支持通过正则匹配来指定行位置
1 | sed -n '/foo/,$p' |
$表示最后一行p是 sedprint命令的缩写
1 | awk '/foo/ {f=1} f' |
- awk 实现行范围的方式与 sed 稍有不同,它在满足匹配
foo这个条件时,将布尔变量f设置为 1,相当于从这一行开始,开启print打印这个默认操作 - awk 的一条 rule 里,可以省略 pattern, 或者省略 action, 但不能同时两个都省略;如果省略 pattern, 则对每个输入行都执行 action, 如果省略 action, 则对每个匹配行执行
printaction。这个例子里面, awk 的 program 包括两条 rules/foo/ {f=1}这条 rule 什么都没有省略f这条 rule 省略了 action, 所以对每个输入行执行printaction
它们两个的效果也是一样的,都是从第一个匹配 foo 的行开始,一直打印到文件结束。
正则匹配 (Regex match)
awk 中一个 rule 中的 pattern 部分可以只是一条 / 括起来的正则表达式,默认这个正则表达式的匹配对象是 $0, 也就是整行, 如
1 | awk '/foo/' |
它实际上是
1 | awk '$0~/foo/ {print $0}' |
它意思是只要当前行里包含 foo 这个字串,就打印这一行。所以 awk 的正则 pattern, 准确来说是用来搜索的
默认情况下是 $0~/foo/, 那么不默认情况下,可以指定哪个 field 去“匹配”, 如
1 | awk '$1~/foo/ && $3!~/bar/ {print}' |
它意思是当前这条记录,如果第1个字段包含 foo 且 第3个字段不包含 bar, 那么就打印整条记录
TeX/LaTex
TeX/LaTeX
TeX 是高德纳(Donald Knuth)发明的编程式排版语言,而 LaTeX 是莱斯利·兰波特(Leslie Lamport)在 TeX 的基础上开发的 TeX 的扩展宏集。
生成 PDF 的工具
- pandoc 标记语言转换领域的"瑞士军刀"
- 将 Markdown 生成 PDF
- TexLive 开发最为活跃的 TeX 发行版之一
- TexLive 是跨平台的,但一般在 Linux 下安装,MacOS 下是 MacTeX, Windows 下是 MiKTeX.
- eisvogel 简洁的 pandoc LaTex 模板
- eisvogel 要求一个完整的 TexLive 的安装环境,但通常像 CentOS 这样的 Linux 发行版自带的 TexLive 并不完整。
How to Install texlive.iso
Quick Install
将 TexLive 的镜像下载并挂载后,通过顶层目录下的 install-tl 这个 Perl 脚本程序安装,整个安装过程要注意以下几点。
mount ISO image
假设在 Linux 下,通过 root 用户或 sudo 挂载镜像文件
1 | mkdir -p /mnt/iso |
因为 ISO 文件系统是只读文件系统,所以如果想在 /mnt/iso 写入时,还需要借助 Linux 的 OverlayFS 进行再次挂载,之后在目录 /mnt/merged 里就有一份可写版的镜像了
1 | mkdir -p /mnt/{upper,work,merged} |
run installer
TexLive 的 installer 是一个 perl script, 提供 text mode 和 GUI mode 两种安装模式.
1 | ======================> TeX Live installation procedure <===================== |
D: 设置安装路径,相当于指定--prefixP: 保存安装的配置到文件texlive.profile, 之后可以直接编辑这个文件,运行install-tl时通过--profile可以直接读取这个文件中的安装配置
create symlinks to standard directories
1 | Options customization: |
最好勾选此选项,避免使用 TexLive 时各种 Not Found, 原因是 TexLive 默认安装路径并不是标准 Linux 可执行程序的路径(如 /usr/bin), 而是 /usr/local/texlive, 如在 x86_64 安装 texlive2022.iso, 则可执行程序被安装在 /usr/local/texlive/2022/bin/x86_64-linux. 假如不想因为该路径没有在 PATH 里,最好就是在安装时直接在 /usr/bin 下创建相应符号链接。
Non-interactive Installation
当你有一份 texlive.profile 时,就可以执行非交互式安装,install-tl 会直接按照 texlive.profile 文件里的配置安装,无需干预
1 | ./install-tl --no-interaction --profile=texlive.profile |
texlive-full
在使用 xelatex, pdflatex 等 latex 程序时,可以常常遇到类似
! LaTeX Error: File 'fontawesome.sty' not found
xxx.sty 这样的报错,一般是缺少某个 texlive 包,但 texlive 的包太多了,如果懒得一个一个安装,可以
sudo apt install texlive-full
find
find 命令
find 命令用来在目录树里查找文件。本文主要介绍 GNU find. 它从每个 starting-point 开始递归搜索,通过求值 expression 的真值来确定输出结果。
find 的命令行组成

- Options
- Starting-point
- Expression
- Tests
- Actions
- Global options
- Position options
- Operators
Examples
-
只在当前目录搜索(不递归)不以 f 或 g 或 h 开头的目录
find . -maxdepth 1 -name '[^fgh]*' -type d-type d: 找目录-type f: 找文件(不包括 symbolic link)-type l: 找符号链接文件
-
排除/proc 和 /tmp 这两个目录
find / -path /proc -prune -o -path /tmp -prune -o -name "README.md"-prune告诉 find 跳过前面的目录,也可以用\( -o \)将多个-path合并,只保留一个-prune
-
只在当前目录查找除了指定及隐藏目录以外的所有目录,打印并删除
find -maxdepth 1 \( -path ./gh -o -path ./aaa -o -path ./mesa-install -o -path ./1.3.290.0 -o -path ./1.3.280.1 \) -prune -o -type d ! -name ".*" -print -exec rm -rf {} \;- 注意匹配隐藏目录时用
.*,.在 shell 里不是通配符 -print: 不让./gh,./aaa这些目录出现在find命令的输出结果中
- 注意匹配隐藏目录时用
-
查找 ~/gh 目录下只有文件属主(u)有执行权限(x)的文件 (精确匹配文件的 permission bits)
find ~/gh -perm u=x -type f
-
查找 ~/gh 目录下文件属主(u)有执行权限(x) 的文件(组用户(g)或其它用户(o)可能有或没有执行权限)
find ~/gh -perm -u=x -type f
GL_ARB_geometry_shader4
My english is poor
A language that doesn’t affect the way you think about programming, is not worth knowing.
– Alan J. Perlis, Recipient of 1966 Turing Award
词汇: nightly
最近在两个地方看到nightly这个词:
drm-tip或drm/drm-tip (我也不知道这两个仓库有什么区别,除了它们的Owner不同)
DRM current development and nightly trees