shell环境:环境变量
vi简介
正则表达式
文本处理

shell 环境


程序获取环境中的数据(即环境变量)来了解本机的配置。虽然大多数程序用配置文件来存储程序设置,一些程序会根据环境变量来调整他们的行为。
shell 在环境中存储了两种基本类型的数据,即环境变量和 shell 变量。

查看环境变量

可以用 bash 的内建命令 set,或者是 printenv 程序来查看环境变量

  • set
    set命令可以显示shell 或环境变量
    set 命令的输出很友好地按照首字母顺序排列

  • printenv
    printenv 只是显示环境变量

    $ printenv | less
    $ printenv USER
    $ printenv PATH
    $ printenv SHELL
    
  • echo 和 alias
    echo 命令来查看某一个变量的内容

    echo $HOME
    

    别名无法通过使用 set 或 printenv 来查看。用不带参数的 alias 来查看别名

    alias
    
  • 一些环境变量

    变量 内容
    DISPLAY 如果你正在运行图形界面环境,那么这个变量就是你显示器的名字。通常,它是 ":0", 意思是由 X 产生的第一个显示器。
    EDITOR 文本编辑器的名字。
    SHELL shell 程序的名字。
    HOME 用户家目录。
    LANG 定义了字符集以及语言编码方式。
    OLD_PWD 先前的工作目录。
    PAGER 页输出程序的名字。这经常设置为/usr/bin/less。
    PATH 由冒号分开的目录列表,当你输入可执行程序名后,会搜索这个目录列表。
    PS1 Prompt String 1. 这个定义了你的 shell 提示符的内容。随后我们可以看到,这个变量 内容可以全面地定制。
    PWD 当前工作目录。
    TERM 终端类型名。类 Unix 的系统支持许多终端协议;这个变量设置你的终端仿真器所用的协议。
    TZ 指定你所在的时区。大多数类 Unix 的系统按照协调时间时 (UTC) 来维护计算机内部的时钟 ,然后应用一个由这个变量指定的偏差来显示本地时间。
    USER 你的用户名

建立shell环境

登录系统后,bash 程序启动,并且会读取一系列称为启动文件的配置脚本,这些文件定义了默认的可供所有用户共享的 shell 环境。然后是读取更多位于我们自己家目录中的启动文件,这些启动文件定义了用户个人的 shell 环境。
有两种 shell 会话类型:一个是登录 shell 会话,另一个是非登录 shell 会话。

  • 登陆shell会话
    会在其中提示用户输入用户名和密码;例如,我们启动一个虚拟控制台会话。登录 shell 会读取一个或多个启动文件

    文件 内容
    /etc/profile 应用于所有用户的全局配置脚本。
    ~/.bash_profile 用户私人的启动文件。可以用来扩展或重写全局配置脚本中的设置。
    ~/.bash_login 如果文件 ~/.bash_profile 没有找到,bash 会尝试读取这个脚本。
    ~/.profile 如果文件 ~/.bash_profile 或文件 ~/.bash_login 都没有找到,bash 会试图读取这个文件。 这是基于 Debian 发行版的默认设置,比方说 Ubuntu。
  • 非登陆shell会话
    非登录 shell 会话通常当我们在 GUI 下启动终端会话时出现

    文件 内容
    /etc/bash.bashrc 应用于所有用户的全局配置文件。
    ~/.bashrc 用户私有的启动文件。可以用来扩展或重写全局配置脚本中的设置。

    非登录 shell 会话也会继承它们父进程的环境设置,通常是一个登录 shell

  • 查看.开头文件
    在普通用户看来,文件 ~/.bashrc 可能是最重要的启动文件,因为它几乎总是被读取。非登录 shell 默认会读取它,并且大多数登录 shell 的启动文件会以能读取 ~/.bashrc 文件的方式来书写

    ls -a
    

PATH变量

当我们输入 ls 后,shell 不会查找整个计算机系统来找到 /bin/ls(ls 命令的全路径名),相反,它查找一个目录列表,这些目录包含在 PATH 变量中。

  • PATH
    PATH 变量经常(但不总是,依赖于发行版)在 /etc/profile 启动文件中设置。
    如:PATH=$PATH:$HOME/bin
  • export
export PATH

这个 export 命令告诉 shell 让这个 shell 的子进程可以使用 PATH 变量的内容

修改shell环境

  • 修改哪个文件?
    按照通常的规则,添加目录到你的 PATH 变量或者是定义额外的环境变量,要把这些更改放置到.bash_profile 文件中(或者其替代文件中,根据不同的发行版。例如,Ubuntu 使用.profile文件)。对于其它的更改,要放到.bashrc 文件中。
    除非你是系统管理员,需要为系统中的所有用户修改默认设置,那么则限定你只能对自己家目录下的文件进行修改。

  • 文本编辑器
    有许多基于文本的编辑器,一些流行的文本编辑器是 nano、vi 和 emacs。

    nano 编辑器是一个简单易用的编辑器,用于替代随 PINE 邮件套件提供的 pico 编辑器。vi 编辑器(在大多数 Linux 系统中被 vim 替代,vim 是 “Vi IMproved” 的简写)是类 Unix 操作系统的传统编辑器。emacs 编辑器最初由 Richard Stallman 写成。它是一个庞大、多用途的,可做任何事情的编程环境。虽然 emacs 很容易获取,但是大多数 Linux 系统很少默认安装它。

  • 修改前备份
    首先创建一个这个文件的备份总是一个不错的主意。这样能避免我们在编辑文件时弄乱文件。创建文件.bashrc 的备份文件。

    $ cp .bashrc .bashrc.bak
    

    另一个建议,不管什么时候你修改配置文件时,给你所做的更改加上注释都是一个好主意。
    Shell 脚本和 bash 启动文件都使用 “#” 符号来开始注释。

激活修改

对于文件.bashrc 的修改不会生效,直到我们关闭终端会话,再重新启动一个新的会话,因为.bashrc 文件只是在刚开始启动终端会话时读取。
可以强迫 bash 重新读取修改过的.bashrc 文件

source .bashrc

vi简介


多练多练多练!!!!

启动和退出vi

  • vi 命令启动vi
  • :q:q!退出vi

命令模式

vi 启动后会直接进入命令模式,这种模式下,几乎每个按键都是一个命令,谨慎输入
行开头的波浪号表示那一行没有文本

编辑模式

  • 插入模式
    按下 “i” 键进入插入模式
    在屏幕底部看到-- INSERT --,接着就可以输入文本了
  • 退出插入模式返回命令模式
    ESC按键
  • 保存工作
    在命令模式下执行 :w
    :wq : 把:w 和:q 命令结合到一起,来完成保存和退出任务
    :w 命令也可以指定可选的文件名。这个的作用就如 “Save As…”

    例如,如果我们正在编辑 foo.txt 文件,想要保存一个副本,叫做 foo1.txt,那么我们可以执行以下命令::w foo1.txt
    注意:当上面的命令以一个新名字保存文件时,它并没有更改你正在编辑的文件的名字。如果你继续编辑,你还是在编辑文件 foo.txt,而不是 foo1.txt

移动光标

vi 命令模式下时,vi 提供了大量的移动命令,其中一些是与 less 共享的。

按键 移动光标
l or 右箭头 向右移动一个字符
h or 左箭头 向左移动一个字符
j or 下箭头 向下移动一行
k or 上箭头 向上移动一行
0 (零按键) 移动到当前行的行首。
^ 移动到当前行的第一个非空字符。
$ 移动到当前行的末尾。
w 移动到下一个单词或标点符号的开头。
W 移动到下一个单词的开头,忽略标点符号。
b 移动到上一个单词或标点符号的开头。
B 移动到上一个单词的开头,忽略标点符号。
Ctrl-f or Page Down 向下翻一页
Ctrl-b or Page Up 向上翻一页
numberG 移动到第 number 行。例如,1G 移动到文件的第一行。
G 移动到文件末尾。

vi 中的许多命令都可以在前面加上一个数字,比方说上面的”G”命令。在命令之前加上一个 数字,我们就可以指定命令执行的次数。例如,命令”5j”导致 vi 向下移动5行。

基本编辑

  • 追加文本

    • a在光标后面插入
    • A在行尾插入
  • 打开一行

    • o 在当前行下方打开一行
    • O 在当前行上方打开一行
  • 撤销修改

    • u 撤销修改
  • 删除文本

    x 按键会删除光标位置的一个字符。可以在 x 命令之前带上一个数字,来指明要删除的字符个数。d 按键更通用一些。跟 x 命令一样,d 命令之前可以带上一个数字,来指定要执行的删除次数。另外,d 命令之后总是带上一个移动命令,用来控制删除的范围

    一些实例:

    命令 删除的文本
    x 当前字符
    3x 当前字符及其后的两个字符。
    dd 当前行。
    5dd 当前行及随后的四行文本。
    dW 从光标位置开始到下一个单词的开头。
    d$ 从光标位置开始到当前行的行尾。
    d0 从光标位置开始到当前行的行首。
    d^ 从光标位置开始到文本行的第一个非空字符。
    dG 从当前行到文件的末尾。
    d20G 从当前行到文件的第20行。
  • 剪切复制和粘贴

    • d 不仅删除文本,且剪切文本到粘贴缓冲区(剪切板)

    • p 粘贴剪切板中的文本到光标位置之后

    • P把文本粘贴到光标之前

    • y 拉(yank复制)文本,如下为一些组合示例

      命令 复制的内容
      yy 当前行。
      5yy 当前行及随后的四行文本。
      yW 从当前光标位置到下一个单词的开头。
      y$ 从当前光标位置到当前行的末尾。
      y0 从当前光标位置到行首。
      y^ 从当前光标位置到文本行的第一个非空字符。
      yG 从当前行到文件末尾。
      y20G 从当前行到文件的第20行。
  • 连接行

    • J 连接光标当前行和下一行

查找和替换

  • 查找一行
    f 命令查找一行,移动光标到下一个所指定的字符上如输入fa 会把光标定位到同一行中 下一个出现的”a”字符上,在一行中执行了字符的查找命令之后,通过输入分号来重复这个查找。

  • 查找整个文件
    /+需要查找的单词或短语然后回车
    n 重复先前的查找

    支持正则查找,参考下一章节

  • 全局查找和替换
    如将一个文本中的Line全部替换成line

    :%s/Line/line/g
    

    解释:

    条目 含义
    : 冒号字符运行一个 ex 命令。
    % 指定要操作的行数。% 是一个快捷方式,表示从第一行到最后一行。另外,操作范围也 可以用 1,5 (从哪一行到哪一行)来代替,或者用 1,$ 来代替,意思是 “ 从第一行到文件的最后一行。” 如果省略了文本行的范围,那么操作只对当前行生效。
    s 指定操作。在这种情况下是,替换(查找与替代)。
    /Line/line 查找类型与替代文本。
    g 这是“全局”的意思,意味着对文本行中所有匹配的字符串执行查找和替换操作。如果省略 g,则 只替换每个文本行中第一个匹配的字符串。

    也可以指定一个需要用户确认的替换命令。通过添加一个”c”字符到这个命令的末尾:%s/Line/line/gc

编辑多个文件

vi file1 file2 file3...

vi 启动后会看到第一个文件内容

  • 文件之间切换
    :n从这个文件切换到下一个文件
    :N回到先前的文件
    • 从一个文件移到另一个文件时,如果当前文件没有保存修改,vi 会阻止我们切换文件,这是 vi 强制执行的政策。在命令之后添加感叹号,可以强迫 vi 放弃修改而转换文件
    • :buffers会显示一个文件列表
    • :buffer,紧跟着要编辑的缓冲器编号(:buffers可查看文件对应的缓冲区编号)来切换文件
  • 打开另一个文件并编辑
    :e紧跟要打开的文件名将会打开另外一个文件

    当文件由:e 命令加载,你将无法用:n:N 命令来切换文件。这时要使用:buffer 命令加缓冲区号码,来切换文件

  • 跨文本复制粘贴
    编辑多个文件时,经常地要复制文件的一部分到另一个正在编辑的文件
    示例:
    vi foo1.txt foo2.txt
    yy
    :buffer 2
    p
    
  • 插入整个文件到另一个文件
    :r 命令(“read” 简称)把指定的文件插入到光标位置之前

正则表达式


简而言之,正则表达式是一种符号表示法,被用来识别文本模式。它与匹配文件和路径名的 shell 通配符比较相似,但其规模更庞大。许多命令行工具和大多数的编程语言都支持正则表达式,以此来帮助解决文本操作问题。然而,并不是所有的正则表达式都是一样的,这就进一步混淆了事情;不同工具以及不同语言之间的正则表达式都略有差异。
我们将会限定 POSIX 标准中描述的正则表达式(其包括了大多数的命令行工具),与许多编程语言(最著名的 Perl 语言)相反,它们使用了更多和更丰富的符号集。
可结合我之前的博客文章正则表达式

grep

本质上,grep 程序会在文本文件中查找一个指定的正则表达式,并把匹配行输出到标准输出。

grep [options] regex [file...]
  • 常用的grep选项

    选项 描述
    -i 忽略大小写。不会区分大小写字符。也可用--ignore-case 来指定。
    -v 不匹配。通常,grep 程序会打印包含匹配项的文本行。这个选项导致 grep 程序 只会不包含匹配项的文本行。也可用--invert-match 来指定。
    -c 打印匹配的数量(或者是不匹配的数目,若指定了-v 选项),而不是文本行本身。 也可用--count 选项来指定。
    -l 打印包含匹配项的文件名,而不是文本行本身,也可用--files-with-matches 选项来指定。
    -L 相似于-l 选项,但是只是打印不包含匹配项的文件名。也可用--files-without-match 来指定。
    -n 在每个匹配行之前打印出其位于文件中的相应行号。也可用--line-number 选项来指定。
    -h 应用于多文件搜索,不输出文件名。也可用--no-filename 选项来指定。

元字符和原义字符

grep monkey jerry*.txt
  • 原义字符
    如上例子,在jerry*.txt(通配符)文件中查找monkey,匹配项所在行至少包含 45个字符,并且按照字符“m”、“o”、“n”、“k”和“y”的顺序出现在匹配行的某处,字符之间没有其它的字符。字符串“monkey”中的所有字符都是原义字符,因此它们匹配本身。
  • 元字符
    元字符,其被用来指定更复杂的匹配项。正则表达式元字符由以下字符组成:
    ^ $ . [ ] { } - ? * + ( ) | \
    

    其它所有字符都被认为是原义字符,反斜杠会被用来创建元序列,元字符也可以被转义为原义字符,而不是被解释为元字符。许多正则表达式元字符,也是对 shell有特殊含义的字符。当我们在命令行中传递包含元字符的正则表达式的时候,把元字符用引号引起来至关重要,这样可以阻止 shell 试图展开它们。

    • .匹配任意字符
    • 锚点^ $,插入符号和美元符号被看作是锚点。这意味着正则表达式只有在文本行的开头或末尾被找到时,才算发生一次匹配
    • 中括号表达式和字符类[]中括号表达式,能够指定一个待匹配字符集合(包含在不加中括号的情况下会被解释为元字符的字符)
    • 否定,在中括号表示式中的第一个字符是一个插入字符^,则剩余的字符被看作是不会在给定
      的字符位置出现的字符集合
    • 字符区域-,如[A-Za-z0-9]

POSIX字符集

  • ASCII 顺序:如字母ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,不同于字典排序:aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ

  • POSIX 相容的应用程序将会使用字典排列顺序而不是 ASCII 顺序,[A-Z] 字符区域按照字典顺序解释的时候,包含除了小写字母“a”之外的所有字母

    $ ls /usr/sbin/[A-Z]*
    /usr/sbin/biosdecode
    /usr/sbin/chat
    /usr/sbin/chgpasswd
    /usr/sbin/chpasswd
    /usr/sbin/chroot
    ...
    

    为了部分解决如上例子中的问题,POSIX 标准包含了大量的字符集(无法表达部分区域,比如[A-M]),其提供了有用的字符区域

    字符集 说明
    [:alnum:] 字母数字字符。在 ASCII 中,等价于:[A-Za-z0-9]
    [:word:] 与[:alnum:]相同, 但增加了下划线字符。
    [:alpha:] 字母字符。在 ASCII 中,等价于:[A-Za-z]
    [:blank:] 包含空格和 tab 字符。
    [:cntrl:] ASCII 的控制码。包含了0到31,和127的 ASCII 字符。
    [:digit:] 数字0到9
    [:graph:] 可视字符。在 ASCII 中,它包含33到126的字符。
    [:lower:] 小写字母。
    [:punct:] 标点符号字符。在 ASCII 中,等价于:
    [:print:] 可打印的字符。在[:graph:]中的所有字符,再加上空格字符。
    [:space:] 空白字符,包括空格,tab,回车,换行,vertical tab, 和 form feed.在 ASCII 中, 等价于:[ \t\r\n\v\f]
    [:upper:] 大写字母。
    [:xdigit:] 用来表示十六进制数字的字符。在 ASCII 中,等价于:[0-9A-Fa-f]
    $ ls /usr/sbin/[[:upper:]]*
    /usr/sbin/MAKEFLOPPIES
    /usr/sbin/NetworkManagerDispatcher
    /usr/sbin/NetworkManager
    

    恢复到传统的排列顺序(ASCII)

    这个 LANG 变量包含了语种和字符集。这个值最初由你安装Linux 系统时所选择的安装语言决定

    $ locale
     LANG=en_US.UTF-8
     LC_CTYPE="en_US.UTF-8"
     LC_NUMERIC="en_US.UTF-8"
     LC_TIME="en_US.UTF-8"
     ....
    

    把这个 LANG 变量设置为 POSIX,来更改 locale,使其使用传统的 Unix 行为(他的字符集使用 U.S. 英语(更准确地说,ASCII))

    [me@linuxbox ~]$ export LANG=POSIX
    

    通过把这条语句添加到你的.bashrc 文件中,你可以使这个更改永久有效

限定符

  • 匹配零次或一次?
  • 匹配零个或多个元素*
  • 匹配一个或多个元素+
  • 匹配特定个数的元素{n,m}

文本处理

基本处理

  • cat

    $ cat > foo.txt
    	The quick brown fox jumped over the lazy dog.    
    

    Ctrl+d 来指示 cat 程序,我们已经到达文件末尾了

     $ cat -A foo.txt
    ^IThe quick brown fox jumped over the lazy dog.  $
    

    -A 选项,其用来在文本中显示非打印字符。
    tab 字符在我们的文本中由 ˆI 字符来表示。这是一种常见的表示方法,意思是“Control-I”,结果证明,它和 tab 字符是一样的。我们也看到一个 $ 字符出现在文本行真正的结尾处,表明我们的文本包含末尾的空格。

    $ cat -ns foo.txt
    1 The quick brown fox
    2
    3 jumped over the lazy dog.
    

    -n,给文本行添加行号
    -s禁止输出多个空白行

  • sort
    对标准输入的内容,或命令行中指定的一个或多个文件进行排序,然后把排序结果发送到标准输出

    $ sort > foo.txt
    c
    b
    a
    [me@linuxbox ~]$ cat foo.txt
    a
    b
    c
    

    如有三个文本文件,想要把它们合并为一个有序的文件,我们可以这样做:

    sort file1.txt file2.txt file3.txt > final_sorted_list.txt
    
    • 常见的 sort 程序选项

      选项 长选项 描述
      -b --ignore-leading-blanks 默认情况下,对整行进行排序,从每行的第一个字符开始。这个选项导致 sort 程序忽略 每行开头的空格,从第一个非空白字符开始排序。
      -f --ignore-case 让排序不区分大小写。
      -n --numeric-sort 基于字符串的长度来排序。使用此选项允许根据数字值执行排序,而不是字母值。
      -r --reverse 按相反顺序排序。结果按照降序排列,而不是升序。
      -k --key=field1[,field2] 对从 field1到 field2之间的字符排序,而不是整个文本行。看下面的讨论。
      -m --merge 把每个参数看作是一个预先排好序的文件。把多个文件合并成一个排好序的文件,而没有执行额外的排序。
      -o --output=file 把排好序的输出结果发送到文件,而不是标准输出。
      -t --field-separator=char 定义域分隔字符。默认情况下,域由空格或制表符分隔。
  • uniq
    uniq 会删除任意重复行,并且把结果发送到标准输出。它常常和 sort 程序一块使用,来清理重复的输出。

    这个 GNU 版本的 sort程序支持一个 -u 选项,其可以从排好序的输出结果中删除重复行

    $ cat > foo.txt
    a
    b
    a
    b
    $ uniq foo.txt
    a
    b
    a
    b
    

    输出结果与原始文件没有差异;重复行没有被删除。实际上,uniq 程序能完成任务,其输入必须是排好序的数据

    $ sort foo.txt | uniq
    a
    b
    
    • 常用的 uniq 选项

      选项 说明
      -c 输出所有的重复行,并且每行开头显示重复的次数。
      -d 只输出重复行,而不是特有的文本行。
      -f n 忽略每行开头的 n 个字段,字段之间由空格分隔,正如 sort 程序中的空格分隔符;然而, 不同于 sort 程序,uniq 没有选项来设置备用的字段分隔符。
      -i 在比较文本行的时候忽略大小写。
      -s n 跳过(忽略)每行开头的 n 个字符。
      -u 只是输出独有的文本行。这是默认的。

切片和切块

  • cut
    cut 程序被用来从文本行中抽取文本,并把其输出到标准输出。它能够接受多个文件参数或者 标准输入。

    • cut 程序选择项

      选项 说明
      -c char_list 从文本行中抽取由 char_list 定义的文本。这个列表可能由一个或多个逗号 分隔开的数值区间组成。
      -f field_list 从文本行中抽取一个或多个由 field_list 定义的字段。这个列表可能 包括一个或多个字段,或由逗号分隔开的字段区间。
      -d delim_char 当指定-f 选项之后,使用 delim_char 做为字段分隔符。默认情况下, 字段之间必须由单个 tab 字符分隔开。
      --complement 抽取整个文本行,除了那些由-c 和/或-f 选项指定的文本。
      $ cut -d ':' -f 1 /etc/passwd | head
      root
      daemon
      bin
      sys
      sync
      games
      man
      lp
      mail
      news
      
  • paste
    paste 命令的功能正好与 cut 相反。它会添加一个或多个文本列到文件中,而不是从文件中抽取文本列。 它通过读取多个文件,然后把每个文件中的字段整合成单个文本流,输入到标准输出。类似于 cut 命令, paste 接受多个文件参数和 / 或标准输入。

    $ paste distros-dates.txt distros-versions.txt
    
  • join
    在某些方面,join 命令类似于 paste,它会往文件中添加列,但是它使用了独特的方法来完成。 一个 join 操作通常与关系型数据库有关联,在关系型数据库中来自多个享有共同关键域的表格的 数据结合起来,得到一个期望的结果。

    $ join distros-key-names.txt distros-key-vernums.txt | head
    

比较文本

  • comm
    comm 程序会比较两个文本文件,并且会显示每个文件特有的文本行和共有的文把行。

    $ comm file1.txt file2.txt
    

    第一列包含第一个文件独有的文本行;
    第二列, 文本行是第二列独有的;
    第三列包含两个文件共有的文本行。

    • comm 支持 -n 形式的选项,这里 n 代表 1,2 或 3。这些选项使用的时候,指定了要隐藏的列。
      如只想输出两个文件共享的文本行, 将隐藏第一列和第二列
      $ comm -12 file1.txt file2.txt
      
  • diff
    类似于 comm 程序,diff 程序被用来监测文件之间的差异

    diff file1.txt file2.txt
    1d0
    < a
    4a4
    > e
    

    其形式为 range operation range , 用来描述要求更改的位置和类型,从而把第一个文件转变为第二个文件:

    • diff 更改命令
    改变 说明
    r1ar2 把第二个文件中位置 r2 处的文件行添加到第一个文件中的 r1 处。
    r1cr2 用第二个文件中位置 r2 处的文本行更改(替代)位置 r1 处的文本行。
    r1dr2 删除第一个文件中位置 r1 处的文本行,这些文本行将会出现在第二个文件中位置 r2 处。
    • 上下文模式

      $ 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
      
      • diff 上下文模式更改指示符
      指示符 意思
      blank 上下文显示行。它并不表示两个文件之间的差异。
      - 删除行。这一行将会出现在第一个文件中,而不是第二个文件内。
      + 添加行。这一行将会出现在第二个文件内,而不是第一个文件中。
      ! 更改行。将会显示某个文本行的两个版本,每个版本会出现在更改组的各自部分。
    • 统一模式

      $ 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
      
      • diff 统一模式更改指示符
      字符 意思
      空格 两个文件都包含这一行。
      - 在第一个文件中删除这一行。
      + 添加这一行到第一个文件中。
  • patch
    patch 程序被用来把更改应用到文本文件中。它接受从 diff 程序的输出,并且通常被用来 把较老的文件版本转变为较新的文件版本

    diff -Naur old_file new_file > diff_file
    
    $ diff -Naur file1.txt file2.txt &gt; patchfile.txt
    $ patch &lt; patchfile.txt
    patching file file1.txt
    $ cat file1.txt
    b
    c
    d
    e
    

运行时编辑

  • tr
    更改字符

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

    tr 命令接受两个参数:要被转换的字符集以及 相对应的转换后的字符集。字符集可以用三种方式来表示:

    1. 一个枚举列表。例如, ABCDEFGHIJKLMNOPQRSTUVWXYZ
    2. 一个字符域。例如,A-Z 。注意这种方法有时候面临与其它命令相同的问题,归因于 语系的排序规则,因此应该谨慎使用。
    3. POSIX 字符类。例如,[:upper:]
    • 大多数情况下,两个字符集应该长度相同;然而,有可能第一个集合大于第二个,如想要把多个字符转换为单个字符

      $ echo "lowercase letters" | tr [:lower:] A
      AAAAAAAAA AAAAAAA
      
    • -s 选项,tr 命令能“挤压”(删除)重复的字符实例:

      [me@linuxbox ~]$ echo "aaabbbccc" | tr -s ab
      abccc
      

      重复的字符必须是相邻的。 如果它们不相邻,挤压会没有效果

      [me@linuxbox ~]$ echo "abcabcabc" | tr -s ab
      abcabcabc
      
  • sed
    sed 是 stream editor(流编辑器)的简称。它对文本流进行编辑,要不是一系列指定的文件, 要不就是标准输入。这里不会详尽讨论,再开篇介绍强大的sed

    $ echo "front" | sed 's/front/back/'
    back
    

    在上面的例子中,这个替换命令由字母 s 来代表,其后跟着查找 和替代字符串,斜杠字符做为分隔符。分隔符的选择是随意的。按照惯例,经常使用斜杠字符, 但是 sed 将会接受紧随命令之后的任意字符做为分隔符

    sed 中的大多数命令之前都会带有一个地址,其指定了输入流中要被编辑的文本行。
    如果省略了地址, 然后会对输入流的每一行执行编辑命令。

    $ echo "front" | sed '1s/front/back/'
    back
    

    给我们的命令添加地址 1,就导致只对仅有一行文本的输入流的第一行执行替换操作

    [me@linuxbox ~]$ echo "front" | sed '2s/front/back/'
    front
    

    没有执行这个编辑命令,因为我们的输入流没有第二行

    • 常用地址表示法

      地址 说明
      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 可能是上述任意的地址形式。
      $ 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
      

      p 命令, 其就是简单地把匹配的文本行打印出来

      • 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 要求两个字符集合具有相同的长度。
  • aspell
    aspell,一款交互式的拼写检查器

    $ cat > foo.txt
    The quick brown fox jimped over the laxy dog.
    $ aspell check foo.txt
    The quick brown fox jimped over the laxy dog.
    1)jumped                        6)wimped
    2)gimped                        7)camped
    3)comped                        8)humped
    4)limped                        9)impede
    5)pimped                        0)umped
    i)Ignore                        I)Ignore all
    r)Replace                       R)Replace all
    a)Add                           l)Add Lower
    b)Abort                         x)Exit
    ?
    

    除非由命令行选项 --dont-backup 告诉 aspell,否则通过追加扩展名.bak 到文件名中, aspell 会创建一个包含原始文本的备份文件。

格式化输出


  • nl – 添加行号
  • fold – 限制文件列宽
  • fmt – 一个简单的文本格式转换器
  • pr – 让文本为打印做好准备
  • printf – 格式化数据并打印出来
  • groff – 一个文件格式系统

参考