1.本节要学的命令(这章有点长,有点难)
paste |
添加一个或多个文本列到文件中,而不是从文件中抽取文本列。 |
join |
join 类似于 paste,它会往文件中添加列,大门时有自己独特方法. |
comm |
比较两个文本文件,显示每个文件特有的文本行和共有的文把行。 |
diff |
类似于 comm 程序,diff 程序被用来监测文件之间的差异。 |
patch |
把更改应用到文本文件中。 |
tr |
更改字符,我们可以把它看作是一种基于字符的查找和替换操作。 |
sed | 它对文本流,即一系列指定的文件或标准输入进行编辑。 |
aspell |
交互式的拼写检查器 |
2.小知识
知识点1:sort命令参数列表?
选项 | 长选项 | 描述 |
---|---|---|
-b | --ignore-leading-blanks | 忽略每行开头的空格,从第一个非空白字符开始排序。 |
-f | --ignore-case | 让排序不区分大小写。 |
-n | --numeric-sort | 基于字符串的数值来排序。使用此选项允许根据数字值执行排序,而不是字母值。 |
-r | --reverse | 按相反顺序排序。结果按照降序排列,而不是升序。 |
-k | --key=field1[,field2] | 对从 field1到 field2之间的字符排序,而不是整个文本行。 |
-m | --merge | 每个参数看作一个预先排好序的文件。把多个文件合并成一个排好序的文件,而没有执行额外的排序。 |
-o | --output=file | 把排好序的输出结果发送到文件,而不是标准输出。 |
-t | --field-separator=char | 定义域分隔字符。默认情况下,域由空格或制表符分隔。 |
知识点2:uniq为什么删除不了重复?
答:因为uniq只能删除相邻重复选项,所以源文件必须是排好序的。
知识点3:uniq常见的的选项参数?
选项 | 说明 |
---|---|
-c | 输出所有的重复行,并且每行开头显示重复的次数。 |
-d | 只输出重复行,而不是特有的文本行。 |
-f n | 忽略每行开头的 n 个字段,字段之间由空格分隔,正如 sort 程序中的空格分隔符; |
-i | 在比较文本行的时候忽略大小写。 |
-s n | 跳过(忽略)每行开头的 n 个字符。 |
-u | 只输出独有的文本行。这是默认的。 |
知识点4:cut常见的选项参数?
选项 | 说明 |
---|---|
-c char_list | 从文本行中抽取由 char_list 定义的文本。这个列表可能由一个或多个逗号 分隔开的数值区间组成。 |
-f field_list | 从文本行中抽取一个或多个由field_list定义的字段。这个列表可能包括一个或多个字段,或由逗号分隔开的字段区间。 |
-d delim_char | 当指定-f 选项之后,使用 delim_char 做为字段分隔符。默认情况下, 字段之间必须由单个 tab 字符分隔开。 |
--complement | 抽取整个文本行,除了那些由-c 和/或-f 选项指定的文本。 |
知识点5:diff的更改命令有哪些?
改变 | 说明 |
---|---|
r1ar2 | 把第二个文件中位置 r2 处的文件行添加到第一个文件中的 r1 处。 |
r1cr2 | 用第二个文件中位置 r2 处的文本行更改(替代)位置 r1 处的文本行。 |
r1dr2 | 删除第一个文件中位置 r1 处的文本行,这些文本行将会出现在第二个文件中位置 r2 处。 |
知识点6:diff的上下文更改指示符?
指示符 | 意思 |
---|---|
blank | 上下文显示行。它并不表示两个文件之间的差异。 |
- | 删除行。这一行将会出现在第一个文件中,而不是第二个文件内。 |
+ | 添加行。这一行将会出现在第二个文件内,而不是第一个文件中。 |
! | 更改行。将会显示某个文本行的两个版本,每个版本会出现在更改组的各自部分。 |
知识点7:sed地址表示法?
n | 行号,n 是一个正整数。 |
$ | 最后一行。 |
/regexp/ | 所有匹配一个 POSIX 基本正则表达式的文本行。注意正则表达式通过 斜杠字符界定。选择性地,这个正则表达式可能由一个备用字符界定,通过\cregexpc 来 指定表达式,这里 c 就是一个备用的字符。 |
addr1,addr2 | 从 addr1 到 addr2 范围内的文本行,包含地址 addr2 在内。地址可能是上述任意 单独的地址形式。 |
first~step | 匹配由数字 first 代表的文本行,然后随后的每个在 step 间隔处的文本行。例如 1~2 是指每个位于奇数行号的文本行,5~5 则指第五行和之后每五行位置的文本行。 |
addr1,+n | 匹配地址 addr1 和随后的 n 个文本行。 |
addr! | 匹配所有的文本行,除了 addr 之外,addr 可能是上述任意的地址形式。 |
知识点8:sed基本编辑命令
命令 | 说明 |
---|---|
= | 输出当前的行号。 |
a | 在当前行之后追加文本。 |
d | 删除当前行。 |
i | 在当前行之前插入文本。 |
p | 打印当前行。默认情况下,sed 程序打印每一行,并且只是编辑文件中匹配 指定地址的文本行。通过指定-n 选项,这个默认的行为能够被忽略。 |
q | 退出 sed,不再处理更多的文本行。如果不指定-n 选项,输出当前行。 |
Q | 退出 sed,不再处理更多的文本行。 |
s/regexp/replacement/ | 只要找到一个 regexp 匹配项,就替换为 replacement 的内容。 replacement 可能包括特殊字符 &,其等价于由 regexp 匹配的文本。另外, replacement 可能包含序列 \1到 \9,其是 regexp 中相对应的子表达式的内容。更多信息,查看 下面 back references 部分的讨论。在 replacement 末尾的斜杠之后,可以指定一个 可选的标志,来修改 s 命令的行为。 |
y/set1/set2 | 执行字符转写操作,通过把 set1 中的字符转变为相对应的 set2 中的字符。 注意不同于 tr 程序,sed 要求两个字符集合具有相同的长度。 |
知识点9:什么是正则表达式的逆参照 ?
答:如果序列 \n
出现在 replacement 中 ,这里 n 是指从 1 到 9 的数字,则这个序列指的是在前面正则表达式中相对应的子表达式。
3.代码实操
[me@linuxbox ~]$ cat > foo.txt
The quick brown fox jumped over the lazy dog.
[me@linuxbox ~]$ cat -A foo.txt
^IThe quick brown fox jumped over the lazy dog.$
注^I是tab,$是包含末尾的空格。
[me@linuxbox ~]$ cat > foo.txt
The quick brown fox
jumped over the lazy dog.
[me@linuxbox ~]$ cat -ns foo.txt
1 The quick brown fox
2
3 jumped over the lazy dog.
注意:-s是禁止输入多个空白行。
[me@linuxbox ~]$ sort > foo.txt
c
b
a
[me@linuxbox ~]$ cat foo.txt
a
b
c
[me@linuxbox ~]$ du -s /usr/share/* | sort -nr | head
509940 /usr/share/locale-langpack
242660 /usr/share/doc
197560 /usr/share/fonts
179144 /usr/share/gnome
146764 /usr/share/myspell
144304 /usr/share/gimp
135880 /usr/share/dict
76508 /usr/share/icons
68072 /usr/share/apps
62844 /usr/share/foomatic
注:du 用来表示最大的磁盘空间用户
[me@linuxbox ~]$ du -s /usr/share/* | sort -nr | head
509940 /usr/share/locale-langpack
242660 /usr/share/doc
197560 /usr/share/fonts
179144 /usr/share/gnome
146764 /usr/share/myspell
144304 /usr/share/gimp
135880 /usr/share/dict
76508 /usr/share/icons
68072 /usr/share/apps
[me@linuxbox ~]$ ls -l /usr/bin | sort -nr -k 5 | head
-rwxr-xr-x 1 root root 8234216 2008-04-0717:42 inkscape
-rwxr-xr-x 1 root root 8222692 2008-04-07 17:42 inkview
62844 /usr/share/foomatic
注:基于文件行中的某个数值排序,-k 5 就是基于第五个进行排序,也就是数字那一列。
[me@linuxbox ~]$ sort --key=1,1 --key=2n distros.txt
Fedora 5 03/20/2006
Fedora 6 10/24/2006
Fedora 7 05/31/2007
注:--key=1,1就是对第一个字段进行排序。而--key=2n是这里面的第二行。
[me@linuxbox ~]$ sort -k 3.7nbr -k 3.1nbr -k 3.4nbr distros.txt
Fedora 10 11/25/2008
Ubuntu 8.10 10/30/2008
SUSE 11.0 06/19/2008
注:-k 3.7就是第3个字段的第七个字符。而nbr就是-n,-b,-r参数
[me@linuxbox ~]$ sort -t ':' -k 7 /etc/passwd | head
me:x:1001:1001:Myself,,,:/home/me:/bin/bash
root:x:0:0:root:/root:/bin/bash
dhcp:x:101:102::/nonexistent:/bin/false
gdm:x:106:114:Gnome Display Manager:/var/lib/gdm:/bin/false
hplip:x:104:7:HPLIP system user,,,:/var/run/hplip:/bin/false
klog:x:103:104::/home/klog:/bin/false
messagebus:x:108:119::/var/run/dbus:/bin/false
[me@linuxbox ~]$ cat > foo.txt
a
b
c
a
b
c
[me@linuxbox ~]$ uniq foo.txt
a
b
c
a
b
c
[me@linuxbox ~]$ sort foo.txt | uniq -c
2 a
2 b
2 c
[me@linuxbox ~]$ cat -A distros.txt
SUSE^I10.2^I12/07/2006$
Fedora^I10^I11/25/2008$
SUSE^I11.0^I06/19/2008$
Ubuntu^I8.04^I04/24/2008$
Fedora^I8^I11/08/2007$
[me@linuxbox ~]$ cut -f 3 distros.txt
12/07/2006
11/25/2008
06/19/2008
04/24/2008
注:-f 3 抽取第三个字段
[me@linuxbox ~]$ expand distros.txt | cut -c 23-
注:通过expand来处理 distros.txt 文件,再使用 cut 命令,来抽取从位置 23 开始到行尾的每一个字符
[me@linuxbox ~]$ cut -d ':' -f 1 /etc/passwd | head
root
daemon
bin
[me@linuxbox ~]$ cut -f 1,2 distros-by-date.txt > distros-versions.txt
[me@linuxbox ~]$ head distros-versions.txt
Fedora 10
Ubuntu 8.10
SUSE 11.0
[me@linuxbox ~]$ cut -f 3 distros-by-date.txt > distros-dates.txt
[me@linuxbox ~]$ head distros-dates.txt
11/25/2008
10/30/2008
06/19/2008
[me@linuxbox ~]$ paste distros-dates.txt distros-versions.txt
11/25/2008 Fedora 10
10/30/2008 Ubuntu 8.10
06/19/2008 SUSE 11.0
注:paster将两个文件字段合并为一个文件
CUSTNUM FNAME ME
======== ===== ======
4681934 John Smith
ORDERNUM CUSTNUM QUAN ITEM
======== ======= ==== ====
3014953305 4681934 1 Blue Widget
[me@linuxbox ~]$ cut -f 1,1 distros-by-date.txt > distros-names.txt
[me@linuxbox ~]$ paste distros-dates.txt distros-names.txt > distros-key-names.txt
[me@linuxbox ~]$ head distros-key-names.txt
11/25/2008 Fedora
10/30/2008 Ubuntu
06/19/2008 SUSE
[me@linuxbox ~]$ cut -f 2,2 distros-by-date.txt > distros-vernums.txt
[me@linuxbox ~]$ paste distros-dates.txt distros-vernums.txt > distros-key-vernums.txt
[me@linuxbox ~]$ head distros-key-vernums.txt
11/25/2008 10
10/30/2008 8.10
06/19/2008 11.0
[me@linuxbox ~]$ join distros-key-names.txt distros-key-vernums.txt | head
11/25/2008 Fedora 10
10/30/2008 Ubuntu 8.10
06/19/2008 SUSE 11.0
[me@linuxbox ~]$ cat > file1.txt
a
b
c
d
[me@linuxbox ~]$ cat > file2.txt
b
c
d
e
[me@linuxbox ~]$ comm file1.txt file2.txt
a
b
c
d
e
注:第一列是第一个文件特有的,第二列是第二个文件所有的。第三列是共有的。
[me@linuxbox ~]$ comm -12 file1.txt file2.txt
b
c
d
注:-12是隐藏第一列和第二列的意思。
[me@linuxbox ~]$ diff file1.txt file2.txt
1d0
< a
4a4
> e
注:
[me@linuxbox ~]$ diff -c file1.txt file2.txt
*** file1.txt 2008-12-23 06:40:13.000000000 -0500
--- file2.txt 2008-12-23 06:40:34.000000000 -0500
***************
*** 1,4 ****
- a
b
c
d
--- 1,4 ----
b
c
d
+ e
注:-c就是上下文模式,这个输出结果以两个文件名和它们的时间戳开头。第一个文件用星号做标记,第二个
文件用短横线做标记。
*** 1,4 **** 其表示第一个文件中从第一行到第四行的文本行。
--- 1,4 ---- 其表示第二个文件中从第一行到第四行的文本行。
-a bcd +e 还是比较好理解的
[me@linuxbox ~]$ diff -u file1.txt file2.txt
--- file1.txt 2008-12-23 06:40:13.000000000 -0500
+++ file2.txt 2008-12-23 06:40:34.000000000 -0500
@@ -1,4 +1,4 @@
-a
b
c
d
+e
注:@ -1,4 +1,4 @@ 这行字符串表示在更改组中描述的第一个文件中的文本行和第二个文件中的文本行。类
似于时间戳,简短些。
空格 两个文件都包含这一行。
- 在第一个文件中删除这一行。
+ 添加这一行到第一个文件中。
[me@linuxbox ~]$ diff -Naur file1.txt file2.txt > patchfile.txt
[me@linuxbox ~]$ patch < patchfile.txt
patching file file1.txt
[me@linuxbox ~]$ cat file1.txt
b
c
d
e
[me@linuxbox ~]$ echo "lowercase letters" | tr a-z A-Z
LOWERCASE LETTERS
[me@linuxbox ~]$ echo "lowercase letters" | tr [:lower:] A
AAAAAAAAA AAAAAAA
[me@linuxbox ~]$ tr -d '\r' < dos_file > unix_file
注:dos_file 是需要被转换的文件,unix_file 是转换后的结果。使用转义序列 \r 来代表回车符
[me@linuxbox ~]$ echo "aaabbbccc" | tr -s ab
abccc
[me@linuxbox ~]$ echo "abcabcabc" | tr -s ab
abcabcabc
[me@linuxbox ~]$ echo "front" | sed 's/front/back/'
back
[me@linuxbox ~]$ echo "front" | sed 's_front_back_'
back
注:就是把front替换成back。
[me@linuxbox ~]$ echo "front" | sed '1s/front/back/'
back
[me@linuxbox ~]$ echo "front" | sed '2s/front/back/'
front
[me@linuxbox ~]$ sed -n '/SUSE/p' distros.txt
SUSE 10.2 12/07/2006
SUSE 11.0 06/19/2008
SUSE 10.3 10/04/2007
SUSE 10.1 05/11/2006
[me@linuxbox ~]$ sed -n '/SUSE/!p' distros.txt
Fedora 10 11/25/2008
Ubuntu 8.04 04/24/2008
Fedora 8 11/08/2007
[me@linuxbox ~]$ sed 's/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/' distros.txt
SUSE 10.2 2006-12-07
Fedora 10 2008-11-25
SUSE 11.0 2008-06-19
Ubuntu 8.04 2008-04-24
Fedora 8 2007-11-08
注:是由sed 's/regexp/replacement/' distros.txt基本模式得出
regexp = [0-9]{2}/[0-9]{2}/[0-9]{4}$
\3-\1-\2 就是三个子表达式,原顺序改成3,1,2的顺序
目的-- MM/DD/YYYY格式到 -> YYYY-MM-DD 即s/A/B/C$/3/2/1,\(和\)转义字符。\3为逆参数。
[me@linuxbox ~]$ echo "aaabbbccc" | sed 's/b/B/'
aaaBbbccc
[me@linuxbox ~]$ echo "aaabbbccc" | sed 's/b/B/g'
aaaBBBccc
注:我们看到虽然执行了替换操作,但是只针对第一个字母 “b” 实例,然而剩余的实例没有更改。通过添加 g 标志, 我们能够更改所有的实例
[me@linuxbox ~]$ aspell check foo.txt