乙巳🐍年

acc8226 的博客

Apache ZooKeeper 是一个开发和维护开源服务器的项目,它支持高度可靠的分布式协调。

下载地址

zookeeper-3.4.14 下载地址
https://mirrors.bfsu.edu.cn/apache/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz

遇到过的问题

Zookeeper 3.5 启动时 8080 端口被占用

通过查阅 Zookeeper3.5 的官方文档,发现这是 Zookeeper3.5 的新特性:

1
New in 3.5.0: The AdminServer is an embedded Jetty server that provides an HTTP interface to the four letter word commands. By default, the server is started on port 8080, and commands are issued by going to the URL "/commands/[command name]", e.g., http://localhost:8080/commands/stat. The command response is returned as JSON. Unlike the original protocol, commands are not restricted to four-letter names, and commands can have multiple names; for instance, "stmk" can also be referred to as "set_trace_mask". To view a list of all available commands, point a browser to the URL /commands (e.g., http://localhost:8080/commands). See the AdminServer configuration options for how to change the port and URLs.

这是 Zookeeper AdminServer,默认使用 8080 端口,它的配置属性如下:

我们可以修改在 zoo.cfg 中修改 AdminServer 的端口:

1
admin.serverPort=8888

保存后,再次启动,Zookeeper 启动成功。

这是 zookeeper 自己搞了一个简易应用服务器,可以查看一些信息

listint and issuing commands
http://localhost:8888/commands

阅读全文 »

whoami
要查看当前登录用户的用户名

who am i
表示打开当前伪终端的用户的用户名

创建用户
useradd 只创建用户,创建完了用 passwd xxx 去设置新用户的密码。

修改密码
passwd 命令是 password 这个英语单词的缩写,表示“密码”

删除用户
deluser newname

单单用 deluser 命令,不加参数的话,只会删除用户,但是不会删除在 /home 目录中的用户目录。如果你想要连此用户的家目录也一并删除,可以加上 –remove-home 这个参数,如下:

1
deluser –remove-home newname

创建组
addgroup是 add 和 group 的缩写,add是英语“添加”的意思,group是英语“群组”的意思。所以addgroup命令用于添加一个新的群组。

1
sudo addgroup siatstudent

删除组
delgroup 是 delete 和 group 的缩写,delete 是英语“删除”的意思,group 是英语“群组”的意思。所以 delgroup 命令用于删除一个已存在的群组。

查看组

chmod 命令:修改文件的访问权限

Linux/Unix 的档案调用权限分为三级 : 档案拥有者、群组、其他。利用 chmod 可以藉以控制档案如何被他人所调用。

https://blog.csdn.net/jiandanjinxin/article/details/51920812

总结

su命令 和 su - 命令最大的本质区别就是:前者只是切换了 root 身份,但 Shell 环境仍然是普通用户的 Shell;而后者连用户和 Shell 环境一起切换成 root 身份了。

参考

Shell 变量

使用 declare 命令创建一个变量名为 tmp 的变量:declare tmp

其实也可以不用 declare 预声明一个变量,直接即用即创建,这里只是告诉你 declare 的作用,这在创建其它指定类型的变量(如数组)时会用到。

使用 = 号赋值运算符,将变量 tmp 赋值为 shiyanlou。注意,与其他语言不同的是, Shell 中的赋值操作,= 两边不可以输入空格,否则会报错。

读取变量的值,使用 echo 命令和 $ 符号($ 符号用于表示引用一个变量的值,初学者经常忘记输入)

通常我们会涉及到的变量类型有三种:

当前 Shell 进程私有用户自定义变量,如上面我们创建的 tmp 变量,只在当前 Shell 中有效。
Shell 本身内建的变量。
从自定义变量导出的环境变量。
也有三个与上述三种环境变量相关的命令:set,env,export。这三个命令很相似,都是用于打印环境变量信息,区别在于涉及的变量范围不同。详见下表:

命令说明
set 显示当前 Shell 所有变量,包括其内建环境变量(与 Shell 外观等相关),用户自定义变量及导出的环境变量。
env 显示与当前用户相关的环境变量,还可以让命令在指定环境中运行。
export 显示从 Shell 中导出成环境变量的变量,也能通过它将自定义变量导出为环境变量。

export 小于 env 小于 set

注意:为了与普通变量区分,通常我们习惯将环境变量名设为大写。

永久生效
但是问题来了,当你关机后,或者关闭当前的 shell 之后,环境变量就没了啊。怎么才能让环境变量永久生效呢?

按变量的生存周期来划分,Linux 变量可分为两类:

  • 永久的:需要修改配置文件,变量永久生效;
  • 临时的:使用 export 命令行声明即可,变量在关闭 shell 时失效。

这里介绍两个重要文件 /etc/bashrc(有的 Linux 没有这个文件) 和 /etc/profile ,它们分别存放的是 shell 变量和环境变量。还有要注意区别的是每个用户目录下的一个隐藏文件:

这个 .profile 只对当前用户永久生效。因为它保存在当前用户的 Home 目录下,当切换用户时,工作目录可能一并被切换到对应的目录中,这个文件就无法生效。

创建 shell 脚本文件

一个简单的示例

1
2
3
4
5
6
7
#!/bin/bash

for ((i=0; i<10; i++));do
echo "hello shell"
done

exit 0

为文件添加可执行权限,否则执行会报错没有权限:chmod 755 hello_shell.sh
并执行脚本 ./hello_shell.sh

添加自定义路径到“ PATH ”环境变量, 注意这里一定要使用绝对路径。PATH=$PATH:/home/shiyanlou/mybin

每个用户的 home 目录中有一个 Shell 每次启动时会默认执行一个配置脚本,以初始化环境,包括添加一些用户自定义环境变量等等。实验楼的环境使用的 Shell 是 zsh,它的配置文件是 .zshrc,相应的如果使用的 Shell 是 Bash,则配置文件为 .bashrc。它们在 etc 下还都有一个或多个全局的配置文件,不过我们一般只修改用户目录下的配置文件。Shell 的种类有很多,可以使用 cat /etc/shells 命令查看当前系统已安装的 Shell。

$ echo "PATH=$PATH:/home/shiyanlou/mybin" >> .zshrc
命令中 >> 表示将标准输出以追加的方式重定向到一个文件中,注意前面用到的 > 是以覆盖的方式重定向到一个文件中

修改和删除已有变量

变量的修改有以下几种方式:

变量设置方式 说明
${变量名#匹配字串} 从头向后开始匹配,删除符合匹配字串的最短数据
${变量名##匹配字串} 从头向后开始匹配,删除符合匹配字串的最长数据
${变量名%匹配字串} 从尾向前开始匹配,删除符合匹配字串的最短数据
${变量名%%匹配字串} 从尾向前开始匹配,删除符合匹配字串的最长数据
${变量名/旧的字串/新的字串} 将符合旧字串的第一个字串替换为新的字串
${变量名//旧的字串/新的字串} 将符合旧字串的全部字串替换为新的字串

变量删除
可以使用 unset 命令删除一个环境变量:
$ unset mypath

如何让环境变量立即生效
前面我们在 Shell 中修改了一个配置脚本文件之后(比如 zsh 的配置文件 home 目录下的 .zshrc),每次都要退出终端重新打开甚至重启主机之后其才能生效,很是麻烦,我们可以使用 source 命令来让其立即生效,如:

1
2
cd /home/shiyanlou
source .zshrc

source 命令还有一个别名就是 .,上面的命令如果替换成 . 的方式就该是:
在使用 . 的时候,需要注意与表示当前路径的那个点区分开。
. ./.zshrc

参考

Linux 基础入门(新版)_Linux - 实验楼

通常 Linux 上的软件安装主要有四种方式

  • 在线安装
  • 从磁盘安装软件包
  • 从二进制软件包安装
  • 从源代码编译安装

在不同的 linux 发行版上面在线安装方式会有一些差异包括使用的命令及它们的包管理工具,因为我们的开发环境是基于 ubuntu 的,所以这里我们涉及的在线安装方式将只适用于 ubuntu 发行版,或其它基于 ubuntu 的发行版如国内的 ubuntukylin(优麒麟),ubuntu 又是基于 debian 的发行版,它使用的是 debian 的包管理工具 dpkg,所以一些操作也适用与 debian。而在一些采用其它包管理工具的发行版如 redhat,centos, fedora 等将不适用(redhat 和 centos 使用 rpm)。

比如我们想安装一个软件,名字叫做 w3m(w3m 是一个命令行的简易网页浏览器),那么输入如下命令:

1
sudo apt-get install w3m

APT 是 Advance Packaging Tool(高级包装工具)的缩写,是 Debian 及其派生发行版的软件包管理器,APT 可以自动下载,配置,安装二进制或者源代码格式的软件包,因此简化了 Unix 系统上管理软件的过程。APT 最早被设计成 dpkg 的前端,用来处理 deb 格式的软件包。现在经过 APT-RPM 组织修改,APT 已经可以安装在支持 RPM 的系统管理 RPM 包。这个包管理器包含以 apt- 开头的多个工具,如 apt-get apt-cache apt-cdrom 等,在 Debian 系列的发行版中使用。

当你在执行安装操作时,首先apt-get 工具会在本地的一个数据库中搜索关于 w3m 软件的相关信息,并根据这些信息在相关的服务器上下载软件安装,这里大家可能会一个疑问:既然是在线安装软件,为啥会在本地的数据库中搜索?要解释这个问题就得提到几个名词了:

软件源镜像服务器
软件源
我们需要定期从服务器上下载一个软件包列表,使用 sudo apt-get update 命令来保持本地的软件包列表是最新的(有时你也需要手动执行这个操作,比如更换了软件源),而这个表里会有软件依赖信息的记录,对于软件依赖,我举个例子:我们安装 w3m 软件的时候,而这个软件需要 libgc1c2 这个软件包才能正常工作,这个时候 apt-get 在安装软件的时候会一并替我们安装了,以保证 w3m 能正常的工作。

apt-get 是用于处理 apt 包的公用程序集,我们可以用它来在线安装、卸载和升级软件包等,下面列出一些apt-get包含的常用的一些工具:

工具 说明
install 其后加上软件包名,用于安装一个软件包
update 从软件源镜像服务器上下载/更新用于更新本地软件源的软件包列表
upgrade 升级本地可更新的全部软件包,但存在依赖问题时将不会升级,通常会在更新之前执行一次update
dist-upgrade 解决依赖关系并升级(存在一定危险性)
remove 移除已安装的软件包,包括与被移除软件包有依赖关系的软件包,但不包含软件包的配置文件
autoremove 移除之前被其他软件包依赖,但现在不再被使用的软件包
purge 与 remove 相同,但会完全移除软件包,包含其配置文件
clean 移除下载到本地的已经安装的软件包,默认保存在/var/cache/apt/archives/
autoclean 移除已安装的软件的旧版本软件包
下面是一些 apt-get 常用的参数:

参数 说明
-y 自动回应是否安装软件包的选项,在一些自动化安装脚本中使用这个参数将十分有用
-s 模拟安装
-q 静默安装方式,指定多个q或者-q=#,#表示数字,用于设定静默级别,这在你不想要在安装软件包时屏幕输出过多时很有用
-f 修复损坏的依赖关系
-d 只下载不安装
–reinstall 重新安装已经安装但可能存在问题的软件包
–install-suggests 同时安装 APT 给出的建议安装的软件包

关于安装,如前面演示的一样你只需要执行apt-get install <软件包名>即可,除了这一点,你还应该掌握的是如何重新安装软件包。 很多时候我们需要重新安装一个软件包,比如你的系统被破坏,或者一些错误的配置导致软件无法正常工作。

你可以使用如下方式重新安装:

1
sudo apt-get --reinstall install w3m

另一个你需要掌握的是,如何在不知道软件包完整名的时候进行安装。通常我们是使用Tab键补全软件包名,后面会介绍更好的方法来搜索软件包。有时候你需要同时安装多个软件包,你还可以使用正则表达式匹配软件包名进行批量安装。

卸载软件

如果你现在觉得 w3m 这个软件不合自己的胃口,或者是找到了更好的,你需要卸载它,那么简单!同样是一个命令加回车 sudo apt-get remove w3m ,系统会有一个确认的操作,之后这个软件便“滚蛋了”。

或者,你可以执行

1
2
3
4
5
# 不保留配置文件的移除
sudo apt-get purge w3m
# 或者 sudo apt-get --purge remove
# 移除不再需要的被依赖的软件包
sudo apt-get autoremove

软件搜索

当自己刚知道了一个软件,想下载使用,需要确认软件仓库里面有没有,就需要用到搜索功能了,命令如下:

1
sudo apt-cache search softname1 softname2 softname3……

apt-cache 命令则是针对本地数据进行相关操作的工具,search 顾名思义在本地的数据库中寻找有关softname1``softname2 …… 相关软件的信息。现在我们试试搜索一下之前我们安装的软件 w3m ,如图:

结果显示了 4 个 w3m 相关的软件,并且有相关软件的简介。

关于在线安装的的内容我们就介绍这么多,想了解更多关于 APT 的内容,你可以参考:

三、使用 dpkg

dpkg 是 Debian 软件包管理器的基础,它被伊恩·默多克创建于 1993 年。dpkg 与 RPM 十分相似,同样被用于安装、卸载和供给和 .deb 软件包相关的信息。

dpkg 本身是一个底层的工具。上层的工具,像是 APT,被用于从远程获取软件包以及处理复杂的软件包关系。"dpkg"是"Debian Package"的简写。

我们经常可以在网络上见到以 deb 形式打包的软件包,就需要使用 dpkg 命令来安装。

dpkg 常用参数介绍:

参数 说明
-i 安装指定 deb 包
-R 后面加上目录名,用于安装该目录下的所有 deb 安装包
-r remove,移除某个已安装的软件包
-I 显示deb包文件的信息
-s 显示已安装软件的信息
-S 搜索已安装的软件包
-L 显示已安装软件包的目录信息

我们先使用apt-get加上-d参数只下载不安装,下载 emacs 编辑器的 deb 包:

1
2
sudo apt-get update
sudo apt-get -d install -y emacs

下载完成后,我们可以查看 /var/cache/apt/archives/ 目录下的内容,如下图:

然后我们将第一个 deb 拷贝到 /home/shiyanlou 目录下,并使用dpkg安装

1
2
3
$ cp /var/cache/apt/archives/emacs24_24.5+1-6ubuntu1.1_amd64.deb ~
# 安装之前参看deb包的信息
$ sudo dpkg -I emacs24_24.5+1-6ubuntu1.1_amd64.deb

如你所见,这个包还额外依赖了一些软件包,这意味着,如果主机目前没有这些被依赖的软件包,直接使用 dpkg 安装可能会存在一些问题,因为dpkg并不能为你解决依赖关系。

1
2
# 使用dpkg安装
$ sudo dpkg -i emacs24_24.5+1-6ubuntu1.1_amd64.deb

跟前面预料的一样,这里你可能出现了一些错误:

我们将如何解决这个错误呢?这就要用到 apt-get 了,使用它的 -f 参数了,修复依赖关系的安装

1
2
sudo apt-get update
sudo apt-get -f install -y

没有任何错误,这样我们就安装成功了,然后你可以运行 emacs 程序

从二进制包安装包

二进制包的安装比较简单,我们需要做的只是将从网络上下载的二进制包解压后放到合适的目录,然后将包含可执行的主程序文件的目录添加进 PATH 环境变量即可,如果你不知道该放到什么位置,请重新复习关于 Linux 目录结构的内容。

英文标题:USEFUL ONE-LINE SCRIPTS FOR SED (Unix stream editor)
原标题:HANDY ONE-LINERS FOR SED (Unix stream editor)

整理:Eric Pement - 电邮:pemente[at]northpark[dot]edu 版本5.5
译者:Joe Hong - 电邮:hq00e[at]126[dot]com

在以下地址可找到本文档的最新(英文)版本:
http://sed.sourceforge.net/sed1line.txt
http://www.pement.org/sed/sed1line.txt

其他语言版本:
中文 - http://sed.sourceforge.net/sed1line_zh-CN.html
捷克语 - http://sed.sourceforge.net/sed1line_cz.html
荷语 - http://sed.sourceforge.net/sed1line_nl.html
法语 - http://sed.sourceforge.net/sed1line_fr.html
德语 - http://sed.sourceforge.net/sed1line_de.html
葡语 - http://sed.sourceforge.net/sed1line_pt-BR.html

文本间隔

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 在每一行后面增加一空行
sed G

# 将原来的所有空行删除并在每一行后面增加一空行。
# 这样在输出的文本中每一行后面将有且只有一空行。
sed '/^$/d;G'

# 在每一行后面增加两行空行
sed 'G;G'

# 将第一个脚本所产生的所有空行删除(即删除所有偶数行)
sed 'n;d'

# 在匹配式样“regex”的行之前插入一空行
sed '/regex/{x;p;x;}'

# 在匹配式样“regex”的行之后插入一空行
sed '/regex/G'

# 在匹配式样 “regex” 的行之前和之后各插入一空行
sed '/regex/{x;p;x;G;}'

编号


1
2
3
4
5
6
7
8
9
10
11
12
# 为文件中的每一行进行编号(简单的左对齐方式)。这里使用了“制表符”
# (tab,见本文末尾关于'\t'的用法的描述)而不是空格来对齐边缘。
sed = filename | sed 'N;s/\n/\t/'

# 对文件中的所有行编号(行号在左,文字右端对齐)。
sed = filename | sed 'N; s/^/ /; s/ *\(.\{6,\}\)\n/\1 /'

# 对文件中的所有行编号,但只显示非空白行的行号。
sed '/./=' filename | sed '/./N; s/\n/ /'

# 计算行数 (模拟 "wc -l")
sed -n '$='

文本转换和替代:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# Unix环境:转换DOS的新行符(CR/LF)为Unix格式

sed 's/.$//' # 假设所有行以CR/LF结束
sed 's/^M$//' # 在bash/tcsh中,将按Ctrl-M改为按Ctrl-V
sed 's/\x0D$//' # ssed、gsed 3.02.80,及更高版本

# Unix环境:转换Unix的新行符(LF)为DOS格式

sed "s/$/`echo -e \\\r`/" # 在ksh下所使用的命令
sed 's/$'"/`echo \\\r`/" # 在bash下所使用的命令
sed "s/$/`echo \\\r`/" # 在zsh下所使用的命令
sed 's/$/\r/' # gsed 3.02.80 及更高版本

# DOS环境:转换Unix新行符(LF)为DOS格式
sed "s/$//" # 方法 1
sed -n p # 方法 2

# DOS环境:转换DOS新行符(CR/LF)为Unix格式。
# 下面的脚本只对UnxUtils sed 4.0.7 及更高版本有效。要识别 UnxUtils 版本的
# sed可以通过其特有的“--text”选项。你可以使用帮助选项(“--help”)看
# 其中有无一个“--text”项以此来判断所使用的是否是 UnxUtils 版本。其它 DOS
# 版本的的sed则无法进行这一转换。但可以用 “tr” 来实现这一转换。
sed "s/\r//" infile >outfile # UnxUtils sed v4.0.7 或更高版本
tr -d \r <infile >outfile # GNU tr 1.22 或更高版本

# 将每一行前导的“空白字符”(空格,制表符)删除
# 使之左对齐
sed 's/^[ \t]*//' # 见本文末尾关于'\t'用法的描述

# 将每一行拖尾的“空白字符”(空格,制表符)删除
sed 's/[ \t]*$//' # 见本文末尾关于'\t'用法的描述

# 将每一行中的前导和拖尾的空白字符删除
sed 's/^[ \t]*//;s/[ \t]*$//'

# 在每一行开头处插入 5 个空格(使全文向右移动 5 个字符的位置)
sed 's/^/ /'

# 以 79 个字符为宽度,将所有文本右对齐
sed -e :a -e 's/^.\{1,78\}$/ &/;ta' # 78 个字符外加最后的一个空格

# 以 79 个字符为宽度,使所有文本居中。在方法 1 中,为了让文本居中每一行的前
# 头和后头都填充了空格。 在方法2中,在居中文本的过程中只在文本的前面填充
# 空格,并且最终这些空格将有一半会被删除。此外每一行的后头并未填充空格。
sed -e :a -e 's/^.\{1,77\}$/ & /;ta' # 方法1
sed -e :a -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/' # 方法2

# 在每一行中查找字串“foo”,并将找到的“foo”替换为“bar”
sed 's/foo/bar/' # 只替换每一行中的第一个“foo”字串
sed 's/foo/bar/4' # 只替换每一行中的第四个“foo”字串
sed 's/foo/bar/g' # 将每一行中的所有“foo”都换成“bar”
sed 's/\(.*\)foo\(.*foo\)/\1bar\2/' # 替换倒数第二个“foo”
sed 's/\(.*\)foo/\1bar/' # 替换最后一个“foo”

# 只在行中出现字串“baz”的情况下将“foo”替换成“bar”
sed '/baz/s/foo/bar/g'

# 将“foo”替换成“bar”,并且只在行中未出现字串“baz”的情况下替换
sed '/baz/!s/foo/bar/g'

# 不管是 “scarlet”“ruby”还是“puce”,一律换成 “red”
sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g' #对多数的sed都有效
gsed 's/scarlet\|ruby\|puce/red/g' # 只对GNU sed有效

# 倒置所有行,第一行成为最后一行,依次类推(模拟“tac”)。
# 由于某些原因,使用下面命令时HHsed v1.5会将文件中的空行删除
sed '1!G;h;$!d' # 方法1
sed -n '1!G;h;$p' # 方法2

# 将行中的字符逆序排列,第一个字成为最后一字,……(模拟“rev”)
sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'

# 将每两行连接成一行(类似“paste”)
sed '$!N;s/\n/ /'

# 如果当前行以反斜杠“\”结束,则将下一行并到当前行末尾
# 并去掉原来行尾的反斜杠
sed -e :a -e '/\\$/N; s/\\\n//; ta'

# 如果当前行以等号开头,将当前行并到上一行末尾
# 并以单个空格代替原来行头的“=”
sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'

# 为数字字串增加逗号分隔符号,将“1234567”改为“1,234,567”
gsed ':a;s/\B[0-9]\{3\}\>/,&/;ta' # GNU sed
sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta' # 其他sed

# 为带有小数点和负号的数值增加逗号分隔符(GNU sed)
gsed -r ':a;s/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g;ta'

# 在每5行后增加一空白行 (在第5,10,15,20,等行后增加一空白行)
gsed '0~5G' # 只对GNU sed有效
sed 'n;n;n;n;G;' # 其他sed

选择性地显示特定行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# 显示文件中的前10行 (模拟“head”的行为)
sed 10q

# 显示文件中的第一行 (模拟“head -1”命令)
sed q

# 显示文件中的最后 10 行 (模拟“tail”)
sed -e :a -e '$q;N;11,$D;ba'

# 显示文件中的最后2行(模拟“tail -2”命令)
sed '$!N;$!D'

# 显示文件中的最后一行(模拟“tail -1”)
sed '$!d' # 方法1
sed -n '$p' # 方法2

# 显示文件中的倒数第二行
sed -e '$!{h;d;}' -e x # 当文件中只有一行时,输入空行
sed -e '1{$q;}' -e '$!{h;d;}' -e x # 当文件中只有一行时,显示该行
sed -e '1{$d;}' -e '$!{h;d;}' -e x # 当文件中只有一行时,不输出

# 只显示匹配正则表达式的行(模拟“grep”)
sed -n '/regexp/p' # 方法1
sed '/regexp/!d' # 方法2

# 只显示“不”匹配正则表达式的行(模拟“grep -v”)
sed -n '/regexp/!p' # 方法1,与前面的命令相对应
sed '/regexp/d' # 方法2,类似的语法

# 查找“regexp”并将匹配行的上一行显示出来,但并不显示匹配行
sed -n '/regexp/{g;1!p;};h'

# 查找“regexp”并将匹配行的下一行显示出来,但并不显示匹配行
sed -n '/regexp/{n;p;}'

# 显示包含“regexp”的行及其前后行,并在第一行之前加上“regexp”所
# 在行的行号 (类似“grep -A1 -B1”)
sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h

# 显示包含“AAA”、“BBB”或“CCC”的行(任意次序)
sed '/AAA/!d; /BBB/!d; /CCC/!d' # 字串的次序不影响结果

# 显示包含“AAA”、“BBB”和“CCC”的行(固定次序)
sed '/AAA.*BBB.*CCC/!d'

# 显示包含“AAA”“BBB”或“CCC”的行 (模拟“egrep”)
sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d # 多数sed
gsed '/AAA\|BBB\|CCC/!d' # 对GNU sed有效

# 显示包含“AAA”的段落 (段落间以空行分隔)
# HHsed v1.5 必须在“x;”后加入“G;”,接下来的3个脚本都是这样
sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'

# 显示包含“AAA”“BBB”和“CCC” 三个字串的段落 (任意次序)
sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'

# 显示包含 “AAA”、“BBB”、“CCC” 三者中任一字串的段落 (任意次序)
sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
gsed '/./{H;$!d;};x;/AAA\|BBB\|CCC/b;d' # 只对GNU sed有效

# 显示包含65个或以上字符的行
sed -n '/^.\{65\}/p'

# 显示包含65个以下字符的行
sed -n '/^.\{65\}/!p' # 方法1,与上面的脚本相对应
sed '/^.\{65\}/d' # 方法2,更简便一点的方法

# 显示部分文本——从包含正则表达式的行开始到最后一行结束
sed -n '/regexp/,$p'

# 显示部分文本——指定行号范围(从第8至第12行,含8和12行)
sed -n '8,12p' # 方法1
sed '8,12!d' # 方法2

# 显示第 52 行
sed -n '52p' # 方法1
sed '52!d' # 方法2
sed '52q;d' # 方法3, 处理大文件时更有效率

# 从第 3 行开始,每7行显示一次
gsed -n '3~7p' # 只对GNU sed有效
sed -n '3,${p;n;n;n;n;n;n;}' # 其他sed

# 显示两个正则表达式之间的文本(包含)
sed -n '/Iowa/,/Montana/p' # 区分大小写方式

选择性地删除特定行


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 显示通篇文档,除了两个正则表达式之间的内容
sed '/Iowa/,/Montana/d'

# 删除文件中相邻的重复行(模拟“uniq”)
# 只保留重复行中的第一行,其他行删除
sed '$!N; /^\(.*\)\n\1$/!P; D'

# 删除文件中的重复行,不管有无相邻。注意hold space所能支持的缓存
# 大小,或者使用GNU sed。
sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'

# 删除除重复行外的所有行(模拟“uniq -d”)
sed '$!N; s/^\(.*\)\n\1$/\1/; t; D'

# 删除文件中开头的10行
sed '1,10d'

# 删除文件中的最后一行
sed '$d'

# 删除文件中的最后两行
sed 'N;$!P;$!D;$d'

# 删除文件中的最后10行
sed -e :a -e '$d;N;2,10ba' -e 'P;D' # 方法1
sed -n -e :a -e '1,10!{P;N;D;};N;ba' # 方法2

# 删除8的倍数行
gsed '0~8d' # 只对GNU sed有效
sed 'n;n;n;n;n;n;n;d;' # 其他sed

# 删除匹配式样的行
sed '/pattern/d' # 删除含pattern的行。当然pattern
# 可以换成任何有效的正则表达式

# 删除文件中的所有空行(与“grep '.' ”效果相同)
sed '/^$/d' # 方法1
sed '/./!d' # 方法2

# 只保留多个相邻空行的第一行。并且删除文件顶部和尾部的空行。
# (模拟“cat -s”)
sed '/./,/^$/!d' #方法1,删除文件顶部的空行,允许尾部保留一空行
sed '/^$/N;/\n$/D' #方法2,允许顶部保留一空行,尾部不留空行

# 只保留多个相邻空行的前两行。
sed '/^$/N;/\n$/N;//D'

# 删除文件顶部的所有空行
sed '/./,$!d'

# 删除文件尾部的所有空行
sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' # 对所有sed有效
sed -e :a -e '/^\n*$/N;/\n$/ba' # 同上,但只对 gsed 3.02.*有效

# 删除每个段落的最后一行
sed -n '/^$/{p;h;};/./{x;/./p;}'

特殊应用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 移除手册页(man page)中的 nroff 标记。在 Unix System V 或 bash shell 下使
# 用'echo'命令时可能需要加上 -e 选项。
sed "s/.`echo \\\b`//g" # 外层的双括号是必须的(Unix 环境)
sed 's/.^H//g' # 在 bash 或 tcsh 中, 按 Ctrl-V 再按 Ctrl-H
sed 's/.\x08//g' # sed 1.5,GNU sed,ssed所使用的十六进制的表示方法

# 提取新闻组或 e-mail 的邮件头
sed '/^$/q' # 删除第一行空行后的所有内容

# 提取新闻组或 e-mail 的正文部分
sed '1,/^$/d' # 删除第一行空行之前的所有内容

# 从邮件头提取“Subject”(标题栏字段),并移除开头的“Subject:”字样
sed '/^Subject: */!d; s///;q'

# 从邮件头获得回复地址
sed '/^Reply-To:/q; /^From:/h; /./d;g;q'

# 获取邮件地址。在上一个脚本所产生的那一行邮件头的基础上进一步的将非电邮
# 地址的部分剃除。(见上一脚本)
sed 's/ *(.*)//; s/>.*//; s/.*[:<] *//'

# 在每一行开头加上一个尖括号和空格(引用信息)
sed 's/^/> /'

# 将每一行开头处的尖括号和空格删除(解除引用)
sed 's/^> //'

# 移除大部分的HTML标签(包括跨行标签)
sed -e :a -e 's/<[^>]*>//g;/</N;//ba'

# 将分成多卷的uuencode文件解码。移除文件头信息,只保留uuencode编码部分。
# 文件必须以特定顺序传给sed。下面第一种版本的脚本可以直接在命令行下输入;
# 第二种版本则可以放入一个带执行权限的shell脚本中。(由Rahul Dhesi的一
# 个脚本修改而来。)
sed '/^end/,/^begin/d' file1 file2 ... fileX | uudecode # vers. 1
sed '/^end/,/^begin/d' "$@" | uudecode # vers. 2

# 将文件中的段落以字母顺序排序。段落间以(一行或多行)空行分隔。GNU sed使用
# 字元“\v”来表示垂直制表符,这里用它来作为换行符的占位符——当然你也可以
# 用其他未在文件中使用的字符来代替它。
sed '/./{H;d;};x;s/\n/={NL}=/g' file | sort | sed '1s/={NL}=//;s/={NL}=/\n/g'
gsed '/./{H;d};x;y/\n/\v/' file | sort | sed '1s/\v//;y/\v/\n/'

# 分别压缩每个.TXT文件,压缩后删除原来的文件并将压缩后的.ZIP文件
# 命名为与原来相同的名字(只是扩展名不同)。(DOS环境:“dir /b”
# 显示不带路径的文件名)。
echo @echo off >zipup.bat
dir /b *.txt | sed "s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/" >>zipup.bat

使用SED:Sed接受一个或多个编辑命令,并且每读入一行后就依次应用这些命令。
当读入第一行输入后,sed对其应用所有的命令,然后将结果输出。接着再读入第二
行输入,对其应用所有的命令……并重复这个过程。上一个例子中sed由标准输入设
备(即命令解释器,通常是以管道输入的形式)获得输入。在命令行给出一个或多
个文件名作为参数时,这些文件取代标准输入设备成为sed的输入。sed的输出将被
送到标准输出(显示器)。因此:

1
2
3
cat filename | sed '10q'         # 使用管道输入
sed '10q' filename # 同样效果,但不使用管道输入
sed '10q' filename > newfile # 将输出转移(重定向)到磁盘上

要了解 sed 命令的使用说明,包括如何通过脚本文件(而非从命令行)来使用这些命令,请参阅《sed & awk》第二版,作者Dale Dougherty和Arnold Robbins(O’Reilly,1997;http://www.ora.com) ,《UNIX Text Processing》,作者Dale Dougherty和Tim O’Reilly(Hayden Books,1987)或者是Mike Arst写的教程——压缩包的名称是“U-SEDIT2.ZIP”(在许多站点上都找得到)。要发掘sed的潜力,则必须对“正则表达式”有足够的理解。正则表达式的资料可以看《Mastering Regular Expressions》作者Jeffrey Friedl(O’reilly 1997)。Unix系统所提供的手册页(“man”)也会有所帮助(试一下这些命令“man sed”、“man regexp”,或者看“man ed”中关于正则表达式的部分),但手册提供的信息比较“抽象”——这也是它一直为人所诟病的。不过,它本来就不是用来教初学者如何使用sed或正则表达式的教材,而只是为那些熟悉这些工具的人提供的一些文本参考。

括号语法:前面的例子对 sed 命令基本上都使用单引号(‘…’)而非双引号(“…”)这是因为sed通常是在Unix平台上使用。单引号下,Unix 的 shell(命令解释器)不会对美元符($)和后引号(...)进行解释和执行。而在双引号下美元符会被展开为变量或参数的值,后引号中的命令被执行并以输出的结果代替后引号中的内容。而在“csh”及其衍生的shell中使用感叹号(!)时需要在其前面加上转义用的反斜杠(就像这样:!)以保证上面所使用的例子能正常运行(包括使用单引号的情况下)。DOS版本的Sed则一律使用双引号(“…”)而不是引号来圈起命令。

‘\t’的用法:为了使本文保持行文简洁,我们在脚本中使用’\t’来表示一个制表符。但是现在大部分版本的sed还不能识别’\t’的简写方式,因此当在命令行中为脚本输入制表符时,你应该直接按TAB键来输入制表符而不是输入’\t’。下列的工具软件都支持’\t’做为一个正则表达式的字元来表示制表符:awk、perl、HHsed、sedmod以及GNU sed v3.02.80。

不同版本的SED:不同的版本间的sed会有些不同之处,可以想象它们之间在语法上会有差异。具体而言,它们中大部分不支持在编辑命令中间使用标签(:name)或分支命令(b,t),除非是放在那些的末尾。这篇文档中我们尽量选用了可移植性较高的语法,以使大多数版本的sed的用户都能使用这些脚本。不过GNU版本的sed允许使用更简洁的语法。想像一下当读者看到一个很长的命令时的心情:

sed -e ‘/AAA/b’ -e ‘/BBB/b’ -e ‘/CCC/b’ -e d

好消息是GNU sed能让命令更紧凑:

sed ‘/AAA/b;/BBB/b;/CCC/b;d’ # 甚至可以写成
sed ‘/AAA|BBB|CCC/b;d’

此外,请注意虽然许多版本的sed接受象“/one/ s/RE1/RE2/”这种在’s’前带有空格的命令,但这些版本中有些却不接受这样的命令:“/one/! s/RE1/RE2/”。这时只需要把中间的空格去掉就行了。

速度优化:当由于某种原因(比如输入文件较大、处理器或硬盘较慢等)需要提高命令执行速度时,可以考虑在替换命令(“s/…/…/”)前面加上地址表达式来提高速度。举例来说:

sed ‘s/foo/bar/g’ filename # 标准替换命令
sed ‘/foo/ s/foo/bar/g’ filename # 速度更快
sed ‘/foo/ s//bar/g’ filename # 简写形式

当只需要显示文件的前面的部分或需要删除后面的内容时,可以在脚本中使用“q”命令(退出命令)。在处理大的文件时,这会节省大量时间。因此:

sed -n ‘45,50p’ filename # 显示第45到50行
sed -n ‘51q;45,50p’ filename # 一样,但快得多

如果你有其他的单行脚本想与大家分享或者你发现了本文档中错误的地方,请发电子邮件给本文档的作者(Eric Pement)。邮件中请记得提供你所使用的sed版本、该sed所运行的操作系统及对问题的适当描述。本文所指的单行脚本指命令行的长度在65个字符或65个以下的sed脚本〔译注1〕。本文档的各种脚本是由以下所列作者所写或提供:

Al Aab # 建立了“seders”邮件列表
Edgar Allen # 许多方面
Yiorgos Adamopoulos # 许多方面
Dale Dougherty # 《sed & awk》作者
Carlos Duarte # 《do it with sed》作者
Eric Pement # 本文档的作者
Ken Pizzini # GNU sed v3.02 的作者
S.G. Ravenhall # 去html标签脚本
Greg Ubben # 有诸多贡献并提供了许多帮助

译注1:大部分情况下,sed 脚本无论多长都能写成单行的形式(通过 -e' 选项和;'号)——只要命令解释器支持,所以这里说的单行脚本除了能写成一行还对长度有所限制。因为这些单行脚本的意义不在于它们是以单行的形式出现。而是让用户能方便地在命令行中使用这些紧凑的脚本才是其意义所在。

Valid XHTML 1.0 Strict

0%