#《快乐的 Linux 命令行》

#diff

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
94
95
96
97
98
99
100
101
$ diff --help
Usage: diff [OPTION]... FILES
Compare FILES line by line.

Mandatory arguments to long options are mandatory for short options too.
--normal output a normal diff (the default)
-q, --brief report only when files differ
-s, --report-identical-files report when two files are the same
-c, -C NUM, --context[=NUM] output NUM (default 3) lines of copied context
-u, -U NUM, --unified[=NUM] output NUM (default 3) lines of unified context
-e, --ed output an ed script
-n, --rcs output an RCS format diff
-y, --side-by-side output in two columns
-W, --width=NUM output at most NUM (default 130) print columns
--left-column output only the left column of common lines
--suppress-common-lines do not output common lines

-p, --show-c-function show which C function each change is in
-F, --show-function-line=RE show the most recent line matching RE
--label LABEL use LABEL instead of file name and timestamp
(can be repeated)

-t, --expand-tabs expand tabs to spaces in output
-T, --initial-tab make tabs line up by prepending a tab
--tabsize=NUM tab stops every NUM (default 8) print columns
--suppress-blank-empty suppress space or tab before empty output lines
-l, --paginate pass output through 'pr' to paginate it

-r, --recursive recursively compare any subdirectories found
--no-dereference don't follow symbolic links
-N, --new-file treat absent files as empty
--unidirectional-new-file treat absent first files as empty
--ignore-file-name-case ignore case when comparing file names
--no-ignore-file-name-case consider case when comparing file names
-x, --exclude=PAT exclude files that match PAT
-X, --exclude-from=FILE exclude files that match any pattern in FILE
-S, --starting-file=FILE start with FILE when comparing directories
--from-file=FILE1 compare FILE1 to all operands;
FILE1 can be a directory
--to-file=FILE2 compare all operands to FILE2;
FILE2 can be a directory

-i, --ignore-case ignore case differences in file contents
-E, --ignore-tab-expansion ignore changes due to tab expansion
-Z, --ignore-trailing-space ignore white space at line end
-b, --ignore-space-change ignore changes in the amount of white space
-w, --ignore-all-space ignore all white space
-B, --ignore-blank-lines ignore changes where lines are all blank
-I, --ignore-matching-lines=RE ignore changes where all lines match RE

-a, --text treat all files as text
--strip-trailing-cr strip trailing carriage return on input

-D, --ifdef=NAME output merged file with '#ifdef NAME' diffs
--GTYPE-group-format=GFMT format GTYPE input groups with GFMT
--line-format=LFMT format all input lines with LFMT
--LTYPE-line-format=LFMT format LTYPE input lines with LFMT
These format options provide fine-grained control over the output
of diff, generalizing -D/--ifdef.
LTYPE is 'old', 'new', or 'unchanged'. GTYPE is LTYPE or 'changed'.
GFMT (only) may contain:
%< lines from FILE1
%> lines from FILE2
%= lines common to FILE1 and FILE2
%[-][WIDTH][.[PREC]]{doxX}LETTER printf-style spec for LETTER
LETTERs are as follows for new group, lower case for old group:
F first line number
L last line number
N number of lines = L-F+1
E F-1
M L+1
%(A=B?T:E) if A equals B then T else E
LFMT (only) may contain:
%L contents of line
%l contents of line, excluding any trailing newline
%[-][WIDTH][.[PREC]]{doxX}n printf-style spec for input line number
Both GFMT and LFMT may contain:
%% %
%c'C' the single character C
%c'\OOO' the character with octal code OOO
C the character C (other characters represent themselves)

-d, --minimal try hard to find a smaller set of changes
--horizon-lines=NUM keep NUM lines of the common prefix and suffix
--speed-large-files assume large files and many scattered small changes
--color[=WHEN] colorize the output; WHEN can be 'never', 'always',
or 'auto' (the default)
--palette=PALETTE the colors to use when --color is active; PALETTE is
a colon-separated list of terminfo capabilities

--help display this help and exit
-v, --version output version information and exit

FILES are 'FILE1 FILE2' or 'DIR1 DIR2' or 'DIR FILE' or 'FILE DIR'.
If --from-file or --to-file is given, there are no restrictions on FILE(s).
If a FILE is '-', read standard input.
Exit status is 0 if inputs are the same, 1 if different, 2 if trouble.

Report bugs to: bug-diffutils@gnu.org
GNU diffutils home page: <http://www.gnu.org/software/diffutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
1
2
3
4
5
$ diff file1.txt file2.txt
1d0
< a
4a4
> e

在默认格式中,每组的更改之前都是一个更改命令,其形式为range operation range,用来描述要求更改的位置和类型,从而把第一个文件转变为第二个文件。

改变 说明
[r1]a[r2] 把第二个文件中位置r2处的文件行添加到第一个文件中的r1
[r1]c[r2] 用第二个文件中位置r2处的文本行更改(替代)位置r1处的文本行
[r1]d[r2] 删除第一个文件中位置r1处的文本行,这些文本行将会出现在第二个文件中位置r2

上下文模式(-c):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ diff -c file1.txt file2.txt
*** file1.txt 2021-04-13 15:27:36.644626792 +0800
--- file2.txt 2021-04-12 15:34:30.758408526 +0800
***************
*** 1,4 ****
- a
b
c
d
--- 1,4 ----
b
c
d
+ e

这个输出结果以两个文件名和它们的时间戳开头。第一个文件用星号做标记,第二个文件用短横线做标记。

*** 1,4 ****表示第一个文件中从第一行到第四行的文本行。
--- 1,4 ----表示第二个文件中从第一行到第四行的文本行。
表示上下文显示行。它并不表示两个文件之间的差异。
-表示删除行,这一行将会出现在第一个文件中。
+表示添加行,这一行将会出现在第二个文件内。
!表示更改行,将会显示某个文本行的两个版本,每个版本会出现在更改组的各自部分。

统一模式(-u):

1
2
3
4
5
6
7
8
9
$ diff -u file1.txt file2.txt
--- file1.txt 2021-04-13 15:27:36.644626792 +0800
+++ file2.txt 2021-04-12 15:34:30.758408526 +0800
@@ -1,4 +1,4 @@
-a
b
c
d
+e

#patch

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
$ patch --help
Usage: patch [OPTION]... [ORIGFILE [PATCHFILE]]

Input options:

-p NUM --strip=NUM Strip NUM leading components from file names.
-F LINES --fuzz LINES Set the fuzz factor to LINES for inexact matching.
-l --ignore-whitespace Ignore white space changes between patch and input.

-c --context Interpret the patch as a context difference.
-e --ed Interpret the patch as an ed script.
-n --normal Interpret the patch as a normal difference.
-u --unified Interpret the patch as a unified difference.

-N --forward Ignore patches that appear to be reversed or already applied.
-R --reverse Assume patches were created with old and new files swapped.

-i PATCHFILE --input=PATCHFILE Read patch from PATCHFILE instead of stdin.

Output options:

-o FILE --output=FILE Output patched files to FILE.
-r FILE --reject-file=FILE Output rejects to FILE.

-D NAME --ifdef=NAME Make merged if-then-else output using NAME.
--merge Merge using conflict markers instead of creating reject files.
-E --remove-empty-files Remove output files that are empty after patching.

-Z --set-utc Set times of patched files, assuming diff uses UTC (GMT).
-T --set-time Likewise, assuming local time.

--quoting-style=WORD output file names using quoting style WORD.
Valid WORDs are: literal, shell, shell-always, c, escape.
Default is taken from QUOTING_STYLE env variable, or 'shell' if unset.

Backup and version control options:

-b --backup Back up the original contents of each file.
--backup-if-mismatch Back up if the patch does not match exactly.
--no-backup-if-mismatch Back up mismatches only if otherwise requested.

-V STYLE --version-control=STYLE Use STYLE version control.
STYLE is either 'simple', 'numbered', or 'existing'.
-B PREFIX --prefix=PREFIX Prepend PREFIX to backup file names.
-Y PREFIX --basename-prefix=PREFIX Prepend PREFIX to backup file basenames.
-z SUFFIX --suffix=SUFFIX Append SUFFIX to backup file names.

-g NUM --get=NUM Get files from RCS etc. if positive; ask if negative.

Miscellaneous options:

-t --batch Ask no questions; skip bad-Prereq patches; assume reversed.
-f --force Like -t, but ignore bad-Prereq patches, and assume unreversed.
-s --quiet --silent Work silently unless an error occurs.
--verbose Output extra information about the work being done.
--dry-run Do not actually change any files; just print what would happen.
--posix Conform to the POSIX standard.

-d DIR --directory=DIR Change the working directory to DIR first.
--reject-format=FORMAT Create 'context' or 'unified' rejects.
--binary Read and write data in binary mode.
--read-only=BEHAVIOR How to handle read-only input files: 'ignore' that they
are read-only, 'warn' (default), or 'fail'.

-v --version Output version info.
--help Output this help.

Report bugs to <bug-patch@gnu.org>.
1
2
3
4
5
6
7
8
9
10
$ diff -Naur file1.txt file2.txt > patchfile.txt
$ cat patchfile.txt
--- file1.txt 2021-04-13 15:27:36.644626792 +0800
+++ file2.txt 2021-04-12 15:34:30.758408526 +0800
@@ -1,4 +1,4 @@
-a
b
c
d
+e
1
2
3
4
5
6
7
8
9
10
11
12
$ cat file1.txt
a
b
c
d
$ patch < patchfile.txt
patching file file1.txt
$ cat file1.txt
b
c
d
e

没有必要指定一个要修补的目标文件,因为diff文件(在统一模式中)已经在标题行中包含了文件名。

#tr

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
$ tr --help
Usage: tr [OPTION]... SET1 [SET2]
Translate, squeeze, and/or delete characters from standard input,
writing to standard output.

-c, -C, --complement use the complement of SET1
-d, --delete delete characters in SET1, do not translate
-s, --squeeze-repeats replace each sequence of a repeated character
that is listed in the last specified SET,
with a single occurrence of that character
-t, --truncate-set1 first truncate SET1 to length of SET2
--help display this help and exit
--version output version information and exit

SETs are specified as strings of characters. Most represent themselves.
Interpreted sequences are:

\NNN character with octal value NNN (1 to 3 octal digits)
\\ backslash
\a audible BEL
\b backspace
\f form feed
\n new line
\r return
\t horizontal tab
\v vertical tab
CHAR1-CHAR2 all characters from CHAR1 to CHAR2 in ascending order
[CHAR*] in SET2, copies of CHAR until length of SET1
[CHAR*REPEAT] REPEAT copies of CHAR, REPEAT octal if starting with 0
[:alnum:] all letters and digits
[:alpha:] all letters
[:blank:] all horizontal whitespace
[:cntrl:] all control characters
[:digit:] all digits
[:graph:] all printable characters, not including space
[:lower:] all lower case letters
[:print:] all printable characters, including space
[:punct:] all punctuation characters
[:space:] all horizontal or vertical whitespace
[:upper:] all upper case letters
[:xdigit:] all hexadecimal digits
[=CHAR=] all characters which are equivalent to CHAR

Translation occurs if -d is not given and both SET1 and SET2 appear.
-t may be used only when translating. SET2 is extended to length of
SET1 by repeating its last character as necessary. Excess characters
of SET2 are ignored. Only [:lower:] and [:upper:] are guaranteed to
expand in ascending order; used in SET2 while translating, they may
only be used in pairs to specify case conversion. -s uses the last
specified SET, and occurs after translation or deletion.

GNU coreutils online help: <http://www.gnu.org/software/coreutils/>
Report tr translation bugs to <http://translationproject.org/team/>
Full documentation at: <http://www.gnu.org/software/coreutils/tr>
or available locally via: info '(coreutils) tr invocation'

tr程序被用来更改字符,可以把它看作是一种基于字符的查找和替换操作。

1
2
$ echo "lowercase letters" | tr a-z A-Z
LOWERCASE LETTERS

tr命令接受两个参数:要被转换的字符集以及相对应的转换后的字符集。比如:一个枚举列表一个字符域或者POSIX 字符类

大多数情况下,两个字符集应该长度相同;然而,有可能第一个集合大于第二个,尤其如果我们想要把多个字符转换为单个字符:

1
2
$ echo "lowercase letters" | tr [:lower:] A
AAAAAAAAA AAAAAAA

tr命令能允许字符从输入流中简单地被删除:

1
tr -d '\r' < dos_file > unix_file

-s选项能删除重复的字符实例(需要重复字符相邻):

1
2
3
4
$ echo "aaabbbccc" | tr -s ab
abccc
$ echo "abcabcabc" | tr -s ab
abcabcabc