常用替换表达式

对一个字符串按每x位进行分割

1
2
# 每8位进行分割,表达式所匹配的含义是:匹配一个位置,左边有字符,右边包含的字符总数是8的倍数
(?<=\w)(?=(\w{8})+\b)

使用 perl 来进行替换

1
2
3
# 配置位置,并不匹配一个具体的字符,锚点
echo 12345678 | perl -p -n -e 's/(?<=\d)(?=(\d{3})+$)/,/g' # 表达式的 $ 是必须的,匹配文本的结束位置
12,345,678

使用 sed 进行替换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 使用捕获型括号
# :start 定义标签,执行替换命令
# t 表示 test,如果替换命令成功执行,则跳转至对应的标签执行,否则结束
$ echo 12345678 | sed '{
:start
s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/ # {} () 需要使用 \ 进行转移表达其特殊含义,这点和一般使用的表达式引擎是有区别的
t start
}'
12,345,678

# 需要理解的一点是,匹配替换是一个循环的过程,直到测试至文本的末尾 (.*[0-9]) 一开始会匹配 '12345678', .* 匹配 '1234567', [0-9] 匹配 '8', 发现后面还需要匹配 3 个数字,于是进行回溯(面包屑),发现 (.*[0-9]) 匹配 '12345' 时,后面刚好有 3 个数字,能够匹配,所以本次匹配成功,所以第一次替换后的结果为 '12345,678'; 第二次替换后的结果为 '12,345,678'


# 使用 s 命令的 p 进行验证 (-n 关闭了默认的打印)
$ echo 12345678 | sed -n '{
:start
s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/p
t start
}'
12345,678
12,345,678

正则表达式的流派与元字符

正则表达式的流派与元字符

不同的正则表达式工具,背后的引擎可能是不同的,相同的正则表达式可能在不同的工具中会获得不同的结果(不同的正则表达式也可能获得相同的结果),所以要注意这种语义的差异,如:

1
2
3
4
5
6
7
# perl regex pattern result
root@desktop-guo:~# echo -e 'july' | grep -z -P '(jul|july)'
july

# egrep result
root@desktop-guo:~# echo -e 'july' | grep -z -E '(jul|july)'
july

正则表达式的更有意义的操作:检查某个正表达式是否能够匹配某个字符串;查找和替换,字符串的更新

程序设计语言处理正则表达式的方式

  • 集成式 (integrated)

    正则表达式是内嵌在语言中的,属于语言的低级语法,如 Perl, 其他两种,不是内建的操作符来处理,由普通的函数接受普通的字符串,将他们作为正则表达式进行处理

  • 程序式 (procedural)

    函数式

  • 面向对象式 (object-oriented)

    通过构造函数及方法,如 Java 通过构造 Pattern、Matcher 对象来实现,当然也提供了函数式的静态方法来使用正则表达式

Unicode 中的行终结符

表示 Unicode code point 描述
LF U+000A ASCII 换行符
VT U+000B ASCII 垂直制表符
FF U+000C ASCII 进纸符
CR U+000D ASCII 回车
CR/LF U+000D U+000A ASCII 回车/换行
NEL U+0085 Unicode 换行
LS U+2028 Unicode 行分隔符
PS U+2029 Unicode 段分隔符

常见模式修饰符字母

字母 模式
i 不区分大小写的匹配模式
x 宽松排列和注释模式
s 点号通配模式(单行模式)
m 增强的行锚点模式(多行模式)

Sed 命令行手册

command description
P 打印 pattern space 中的一行
D 删除当前 pattern space 的一行,并重新开始新的循环
N 读取输入源的下一行,并追加到 pattern space,使用 newline 分隔,并继续当前循环的执行(execution of cycle)

一行指的是,使用行分隔符分隔

sed 命令中,似乎有这样的规约:大写字母的命令总是与多行数据相关的;通常利用这些命令实现一个队列 FIFO.

例子:移除文件中最后5行:

1
2
3
4
5
6
7
cat -n inputfile | sed -En -e '
1 { N;N;N;N } # ensure the pattern space contains *five* lines

N # append a sixth line onto the queue
P # Print the head of the queue
D # Remove the head of the queue
'

利用可以追加(N - read and append)到 pattern space 的命令,以及删除(D) pattern space 中首行的命令,可以在 pattern space 中保持一个大小为 5 的队列,当第 6 行的数据追加到 pattern space 时,出队,即打印(P)队首的元素, 并删除(D)队首的行, 最终 pattern space 中保留了最后 5 行的数据,其余行已经打印,到达文件末尾,执行结束。

参考链接

Complete Sed Command Guide

Shell 基础

如何使用函数库

1
2
3
4
5
6
7
8
9
10
$ cat .bashrc
...

# 每次启动一个新shell的时候,都会由shell重新载入函数库
. ~/libraries/basicfuncs

# none interactive shell environment init (before shell script executing)
# 为非交互式shell引入函数库,避免脚本重复定义
BASH_ENV=~/.none_interactive_bashrc
export BASH_ENV
1
2
3
$ cat .none_interactive_bashrc
. ~/libraries/basicfuncs
NONE_INTERACTIVE_ARG="Aloah"