32、UNIX文本处理全攻略:从基础到高级应用

UNIX文本处理全攻略:从基础到高级应用

利用make工具优化文档处理流程

在文档制作的最后阶段,有诸多细节需要用户留意。为确保文档的最终生成万无一失, make 工具能发挥巨大作用。以下是一些需要确保完成的事项:
1. 所有相关章节都以最新版本打印,防止文件的最后修改未被纳入印刷版。
2. 利用自动工具对书籍进行校对,如 proof double 脚本(若有 wwb 也可使用),同时要满足并移除文本中嵌入的所有“审核注释”。
3. 打印更新后的目录和索引。

make 工具虽然能指定书籍各部分所需的文件和格式选项,但存在占用大量磁盘空间来保存格式化输出文件的问题。不过,我们可以通过创建零长度文件来解决这一限制。具体操作是在格式化源文件时,使用 touch 命令更新该零长度文件。例如,在 format 脚本末尾添加 touch print/$file ,或者将 touch 命令放入 makefile 中。

下面是一个简单的 makefile 示例:

book : print/ch01 print/ch02 print/ch03 ...
print/ch01 : ch01
    sh /usr/local/bin/format -mS -rvl -rS2 ch01
    touch print/ch01
print/ch02 : ch02
    sh /usr/local/bin/format -mS -P -rvl -rS2 ch02
    touch print/ch02

为了使 makefile 更具通用性和易修改性,可以使用变量:

FORMAT: sh /usr/local/bin/format
OPTIONS: -mS -P -rvl -rS2
book : print/ch01 print/ch02 print/ch03 ...
print/ch01 : ch01
    $(FORMAT) $(OPTIONS) ch01
    touch print/ch01
print/ch02 : ch02
    $(FORMAT) $(OPTIONS) ch02
    touch print/ch02

make 使用的变量设置方式与shell变量类似,但引用时需用括号括起来并加上美元符号。用户可以轻松编辑 OPTIONS 变量来添加或移除选项。

为了确保索引和目录的更新,可在 makefile 中添加以下依赖关系和创建指令:

book: print/ch01 ... proof/ch01 ... book-index book-toc
print/ch01 : ch01
book-index : index/ch01 index/ch02 ...
    cat index/* | sh /usr/local/bin/indexprog > book-index
book.toc : toc/ch01 ... figlist/ch01 ... tablist/ch01 ...
    echo .ta \n(LLu-5n \n(LLuR > book-toc
    echo .ce >> book-toc
    echo \f3TABLE OF CONTENTS\fP >> book-toc
    echo .sp 2 >> book-toc
    echo "\t\f3Page\fP" >> book-toc
    cat toc/ch01 ... toc/appz >> book-toc
    echo ' .bp' >> book-toc
    cat figlist/ch01 ... figlist/appz >> book-toc
    echo ' .bp' >> book-toc
    cat tablist/ch01 ... tablist/appz >> book-toc
toc/ch01 : ch01
    $(FORMAT) $(OPTIONS) -X ch01
toc/ch02 : ch02
    $(FORMAT) $(OPTIONS) -X ch02
index/ch01 : ch01
    $(FORMAT) $(OPTIONS) -X ch01
figlist/ch01 : ch01
    $(FORMAT) $(OPTIONS) -X ch01
tablist/ch01 : ch01
    $(FORMAT) $(OPTIONS) -X ch01

通过输入 $ make book.toc ,系统会自动编译目录。若文件有更改,会重新格式化源文件以生成新的目录条目。

此外,还可以添加其他“目标”,如检查每章是否校对。创建一个伪目标 proof ,当输入 $ make proof 时,会根据 makefile 中的规则自动强制校对文档。 print 目录也可作为伪目标,方便打印单个章节。输入 $ make book ,可一次性打印整本书及其附属内容。若想在执行时不显示格式化命令,可使用 -s 选项或在 makefile 顶部添加 .SILENT:

为了简化复杂 makefile 的创建过程,可以编写一个shell脚本 buildmake

if [ $# -eq 0 ]; then
    echo 'USAGE : buildmake files'
    echo ' (You must specify the files that make up the book)'
    exit
fi
if [ ! -d print ]; then
    mkdir print
    mkdir proof
fi
if [ ! -d index ]; then
    mkdir index
fi
if [ ! -d toc ]; then
    mkdir toc
    mkdir figlist
    mkdir tablist
fi
for x; do
    prifiles="$prifiles print/$x"
    profiles="$profiles proof/$x"
    tcfiles="$tcfiles toc/$x"
    xfiles="$xfiles index/$x"
    fgfiles="$fgfiles figlist/$x"
    tbfiles="$tbfiles toc/$x"
done
echo ".SILENT:" > makefile
echo "FORMAT = sh /usr/local/bin/format" >> makefile
echo "OPTIONS = -mS" >> makefile
echo "INDEXPROG = sh /usr/local/bin/indexprog" >> makefile
echo "book : $prifiles $profiles book-toc book.index" >> makefile
echo "book.index : $xfiles/" >> makefile
echo -e "\tcat $xfiles | $(INDEXPROG) > book.index" >> makefile
echo -e "\t$(FORMAT) $(OPTIONS) book.index" >> makefile
echo "book-toc : $tcfiles" >> makefile
echo -e "\techo .ta \n(LLu-5n \n(LLuR > book-toc" >> makefile
echo -e "\techo .ce >> book-toc" >> makefile
echo -e "\techo \f3TABLE OF CONTENTS\fP >> book-toc" >> makefile
echo -e "\techo .sp 2 >> book-toc" >> makefile
echo -e "\techo \"\t\f3Page\fP\" >> book-toc" >> makefile
echo -e "\tcat /work/lib/toc - top > book-toc" >> makefile
echo -e "\tcat $tcfiles >> book-toc" >> makefile
echo -e "\techo .bp >> book-toc" >> makefile
echo -e "\tcat $fgfiles >> book-toc" >> makefile
echo -e "\techo .bp >> book-toc" >> makefile
echo -e "\tcat $tbfiles >> book-toc" >> makefile
echo -e "\t$(FORMAT) $(OPTIONS) book-toc" >> makefile
for x; do
    echo "print/$x : $x" >> makefile
    echo -e "\t$(FORMAT) $(OPTIONS) $x" >> makefile
    echo "proof/$x : $x" >> makefile
    echo -e "\techo $x has not been proofed" >> makefile
    echo "toc/$x : $x" >> makefile
    echo -e "\t$(FORMAT) $(OPTIONS) -x $x" >> makefile
    echo "index/$x : $x" >> makefile
    echo -e "\t$(FORMAT) $(OPTIONS) -x $x" >> makefile
done

用户只需输入 $ buildmake files ,即可创建复杂的 makefile ,还可手动编辑指定格式化选项的第一行。

UNIX文本处理工具命令总结

UNIX中有多种文本处理工具,下面将对其命令进行详细总结。

模式匹配语法

许多UNIX文本处理程序(如 ed ex vi sed grep )支持通过文本模式(正则表达式)进行搜索和替换。正则表达式由普通字符和特殊字符组合而成,以下是一些特殊字符及其用途:
| 特殊字符 | 用途 |
| ---- | ---- |
| . | 匹配除换行符外的任何单个字符 |
| * | 匹配前一个字符(包括正则表达式指定的字符)的任意数量(包括零个) |
| [ ] | 匹配方括号内的任意一个字符,可指定字符范围,如 [A-Z] ,若以 ^ 开头则匹配方括号外的字符 |
| \{n,m\} | 匹配前一个字符的出现次数范围, \{n\} 表示精确匹配n次, \{n,\} 表示至少匹配n次, \{n,m\} 表示匹配n到m次 |
| ^ | 要求后续正则表达式出现在行首 |
| $ | 要求前面的正则表达式出现在行尾 |
| \ | 将后续特殊字符视为普通字符 |
| \(\) | 将括号内的模式保存到特殊空间,最多可保存9个模式,可通过 \1 - \9 在替换中“重放” |
| \n | 匹配之前由 \(\) 保存的第n个模式 |

egrep awk 还使用扩展的元字符集:
| 元字符 | 用途 |
| ---- | ---- |
| regexp+ | 匹配正则表达式的一次或多次出现 |
| regexp? | 匹配正则表达式的零次或一次出现 |
| regexp \| regexp | 匹配包含任一正则表达式的行 |
| (regexp) | 用于复杂正则表达式的分组 |

ex 中的正则表达式还有一些不同的扩展:
| 扩展 | 用途 |
| ---- | ---- |
| \< | 限制后续模式仅在单词开头匹配 |
| \> | 限制后续模式仅在单词结尾匹配 |
| \u | 附加到替换字符串,将替换字符串的首字符转换为大写 |
| \U | 附加到替换字符串,将整个替换字符串转换为大写 |
| \l | 附加到替换字符串,将替换字符串的首字符转换为小写 |
| \L | 附加到替换字符串,将整个替换字符串转换为大写 |

vi编辑器
  • 命令行语法 :有两种方式调用 vi 编辑器: vi [options] file(s) vi view file(s) 。若未指定文件名, vi 会打开一个可通过 :f 命令命名或在保存时命名的文件。若指定多个文件,第一个文件将被打开编辑,使用 :n 可打开下一个文件。 view 命令以只读模式打开第一个文件,更改无法保存。
    • 选项
      • -l :打开文件编辑LISP程序
      • -r :恢复文件
      • -R :以只读模式打开文件,与 view 相同
      • -ttag :从标签开始
      • -X :打开加密文件
      • + :打开文件到最后一行
      • + n :打开文件到第n行
      • + /pattern :打开文件到模式的首次出现位置
      • -wn :将窗口设置为n行
  • 操作模式 :文件打开后进入命令模式,可从命令模式进入插入模式、执行编辑命令、移动光标、调用 ex 命令或UNIX shell、保存或退出文件。以下命令可进入插入模式: a A i I o O R s S ,在插入模式下可输入新文本,按 ESCAPE 键返回命令模式。
  • 命令语法 :编辑命令的语法为 [n] operator [n] object ,其中 operator 是基本编辑操作符(如 c - 更改、 d - 删除、 y - 复制), object 是定位光标在文件中的命令(如 word sentence paragraph section 等), n 表示操作执行的次数或操作的对象数量。
  • 状态行命令 :大多数命令输入时不在屏幕上回显,但以下命令在屏幕底部的状态行回显:
    • / ? :开始向前或向后的模式匹配搜索
    • * :调用 ex 命令
    • ! :调用以缓冲区对象为输入并将输出替换该对象的UNIX命令
    • 状态行输入的命令需按 RETURN 键执行,错误消息和 *G 命令的输出也显示在状态行。

以下是 vi 命令的部分总结:
| 命令 | 用途 |
| ---- | ---- |
| " @ | 重复上一个命令(插入、更改或删除) |
| @buffer | 执行缓冲区中存储的命令 |
| a | 在光标后追加文本 |
| A | 在行尾追加文本 |
| b | 后退到当前行单词的开头 |
| B | 后退到单词,忽略标点符号 |
| c | 更改操作符 |
| d | 删除操作符 |
| e | 移动到单词末尾 |
| f | 在当前行向前查找下一个输入的字符 |
| F | 在当前行向后查找下一个输入的字符 |
| ^F | 向前滚动一个窗口 |
| g | 未使用 |
| G | 转到指定行或文件末尾 |
| ^G | 在状态行打印文件信息 |
| h | 左箭头光标键 |
| H | 将光标移动到起始位置 |
| i | 在光标前插入文本 |
| I | 在行首插入文本 |
| J | 连接两行 |
| k | 上箭头光标键 |
| l | 右箭头光标键 |
| L | 将光标移动到窗口的最后一个位置 |
| m | 在寄存器(a - z)中标记当前光标位置 |
| M | 将光标移动到窗口的中间位置 |
| n | 重复上一个搜索命令 |
| N | 反向重复上一个搜索命令 |
| o | 在当前行下方打开一行 |
| O | 在当前行上方打开一行 |
| p | 将复制或删除的文本放在光标后或下方 |
| P | 将复制或删除的文本放在光标前或上方 |
| q | 退出 vi 并调用 ex |
| r | 用下一个输入的字符替换光标处的字符 |
| R | 替换字符 |
| s | 更改光标下的字符为输入的字符 |
| S | 更改整行 |
| t | 将光标向前移动到下一个输入字符之前的字符 |
| T | 将光标向后移动到下一个输入字符之后的字符 |
| u | 撤销上一次更改 |
| U | 恢复当前行,丢弃更改 |
| v | 未使用 |
| V | 未使用 |
| w | 移动到下一个单词的开头 |
| W | 移动到下一个单词的开头,忽略标点符号 |
| x | 删除光标下的字符 |
| X | 删除光标前的字符 |
| y | 复制操作符 |
| Y | 复制当前行 |
| z | 重绘屏幕,根据后续的 CR (顶部)、 . (中间)、 - (底部)重新定位光标 |
| ZZ | 退出编辑器,保存更改 |

vi set 选项可通过 :set 命令指定,以下是部分选项:
| 选项(缩写) | 默认值 | 描述 |
| ---- | ---- | ---- |
| autoindent (ai) | noai | 每行缩进与上一行相同的级别,与 shiftwidth 选项一起使用 |
| autoprint (ap) | | 每次编辑器命令后显示更改(全局替换时显示最后一次替换) |
| autowrite (aw) | noaw | 如果文件在使用 :n 打开另一个文件或使用 :! 执行UNIX命令之前有更改,自动保存文件 |
| beautify (bf) | nobf | 输入时忽略所有控制字符(除制表符、换行符或换页符) |
| directory (dir) | =tmp | 指定 ex 存储缓冲区文件的目录(目录必须可写) |
| edcompatible | noed-compatible | 在替换命令中使用类似 ed 的功能 |
| errorbells (eb) | errorbells = 8 | 错误消息响铃 |
| hardtabs (ht) | | 定义终端硬件制表符的边界 |
| ignorecase (ic) | noic | 搜索时忽略大小写 |
| lisp | nolisp | 以适当的LISP格式插入缩进, () {} [[ ]] 具有LISP含义 |
| list | nolist | 制表符打印为 \| ,行尾标记为 $ ,用于区分行尾字符是制表符还是空格 |
| magic | magic | 通配符 . * [ 在模式中具有特殊含义 |
| mesg | mesg | 允许在 vi 编辑时在终端显示消息 |
| number (nu) | nonu | 在编辑会话期间在屏幕左侧显示行号 |
| open | open | 允许从 ex 进入打开或可视模式 |
| optimize (opt) | noopt | 打印多行时删除行尾的回车符,在打印带有前导空白的行时加快哑终端的输出速度 |
| paragraphs (para) | =IPLPPPQP LIPPlPiPbP | 定义段落分隔符,用于 ( I 移动 |
| prompt | prompt | 设置 ex 提示符 : |
| readonly (ro) | nor0 | 除非在写入( w ZZ autowrite )后使用 ! ,否则任何文件写入操作将失败 |
| redraw (re) | noredraw | 编辑时终端重绘屏幕,默认值取决于行速度和终端类型, noredraw 在慢速哑终端上有用 |
| remap | remap = 5 | 允许嵌套映射序列 |
| report | | 触发屏幕底部警告消息的大编辑操作的大小(即单个编辑影响的行数) |
| scroll | = [1/2 window] | 屏幕滚动的量 |
| sections | =SHNHH HU | 定义章节分隔符,用于 { } 移动 |
| shell (sh) | /bin/sh | 用于shell转义( :! )和shell命令( :sh )的shell路径名,值从shell环境派生 |
| shiftwidth (sw) | sw = a | 定义使用 >> << 命令在 autoindent 选项中缩进的空格数 |
| showmatch (sm) | nosm | 在 vi 中输入 ) ] 时,光标短暂移动到匹配的 ( { ,若匹配不在屏幕上则响铃,对编程非常有用 |
| showmode (smd) | nosmd | 输入模式时在命令行打印 Input Mode 字符串(仅适用于System V, Release 2 vi ) |
| slowopen (slow) | | 插入时暂停显示,默认值取决于行速度和终端类型 |
| tabstop (ts) | = 8 | 设置编辑会话期间制表符缩进的空格数(打印机仍使用系统制表符8) |
| taglength (tl) | = 0 | 定义标签的有效字符数,默认值为0表示所有字符都有效 |
| tags | =tags | 包含标签的文件路径名,默认情况下系统搜索 /usr/lib/tags 和当前目录中的 tags 文件 |
| term | | 终端类型 |
| terse | noterse | 显示更简洁的错误消息 |
| timeout | timeout | 宏在1秒后“超时” |
| tttype | | 终端类型 |
| warn | warn | 显示“自上次更改后未写入”的警告 |
| window (W) | | 在屏幕上显示文件的一定行数,默认值取决于行速度和终端类型 |
| wrapscan (ws) | ws | 搜索环绕文件末尾 |
| wrapmargin (wm) | = 0 | 定义右边界,若大于零则自动插入回车符断行 |
| writeany (wa) | nowa | 允许保存到任何文件 |

mermaid流程图如下:

graph LR
    A[开始] --> B[打开文件]
    B --> C{命令模式}
    C --> D[插入模式]
    C --> E[编辑命令]
    C --> F[移动光标]
    C --> G[调用ex命令]
    C --> H[调用UNIX shell]
    C --> I[保存或退出]
    D --> C[按ESC返回命令模式]

以上就是UNIX文本处理中 make 工具和 vi 编辑器的相关内容,掌握这些知识可以帮助你更高效地进行文本处理和文档制作。

ex编辑器

ex 编辑器是一种行编辑器,也是屏幕编辑器 vi 的基础。所有 ex 命令都作用于文件中的当前行或一系列行。在 vi 中, ex 命令需以冒号开头,并通过按 RETURN 键执行;在 ex 本身中,冒号作为提示符。

要从UNIX提示符进入 ex ,可使用命令: ex filename ,同时也可使用调用 vi 时的选项。在 vi 中,可使用 Q 命令退出 vi 并进入 ex 。退出 ex 的命令如下:
- x :退出并保存更改
- q! :不保存更改直接退出
- vi :从 ex 进入 vi

vi 中输入 ex 命令的格式为: :address command options ,其中冒号表示 ex 命令, address 是行号或行范围,是命令的作用对象。命令可使用以下选项:
| 选项 | 用途 |
| ---- | ---- |
| parameters | 表示可提供额外信息,参数可以是文件名 |
| count | 命令重复执行的次数 |
| flag | 表示命令的变体形式 |
| #, p, 和 l | 表示打印格式 |

需注意,与 vi 命令不同, count 不能放在命令前面,否则会被当作地址。例如, d3 表示从当前行开始删除三行,而 3d 表示删除第三行。输入地址和命令时,会在状态行回显,按 RETURN 键执行命令。

地址的指定规则如下:
- 若未指定地址,命令作用于当前行。
- 若指定行范围,格式为 x,y ,其中 x y 是起始和结束行号,且 x 必须在 y 之前。使用 ; 代替 , 时,会先将当前行设置为 x 再解释 y
- 1,$ 表示文件中的所有行。

常用的地址符号如下:
| 符号 | 用途 |
| ---- | ---- |
| . | 当前行 |
| n | 绝对行号 |
| $ | 最后一行 |
| % | 所有行,等同于 1,$ |
| x -/+ n | x 行之前或之后的第 n 行 |
| - [n] | 前 n 行 |
| + [n] | 后 n 行 |
| 'x | 标记为 x 的行 |
| '' | 上一个上下文 |
| /pat/ ?pat? | 向前或向后匹配到 pat 的行 |

以下是部分 ex 命令总结:
| 命令 | 用途 |
| ---- | ---- |
| abbrev ab [string text] | 定义输入 string 时自动转换为 text ,若未指定则列出所有缩写 |
| [address] a [ ! ] text | 在指定地址后追加文本, ! 标志可在输入文本时切换 autoindent 设置 |
| args | 打印参数列表成员,当前参数用方括号括起来 |
| [address] c [ ! ] text | 用 text 替换指定行, ! 标志可在输入文本时切换 autoindent 设置 |
| [address] co destination | 将指定地址的行复制到目标地址, t copy 的同义词 |
| [address] d [bufSer] | 删除指定地址的行,若指定 bufSer ,则将文本保存或追加到命名缓冲区 |
| e [ ! ] [+n] file | 开始编辑文件, ! 标志不警告未保存的更改, +n 从第 n 行开始编辑 |
| f [filename] | 更改当前文件名,若未指定则打印文件当前状态 |
| [address] g [ ! ] /pattern / [commands] | 对包含 pattern 的所有行执行命令,若未指定命令则打印这些行, ! 标志对不包含 pattern 的行执行命令 |
| [address] i [ ! ] text | 在指定地址前插入文本, ! 标志可在输入文本时切换 autoindent 设置 |
| [address] j [count] | 将指定范围内的文本放在一行,调整空格 |
| [address] k char | 用 char 标记指定地址的行 |
| [address] m destination | 将指定地址的行移动到目标地址 |
| n [ ! ] [ [+command] filelist] | 编辑命令行参数列表中的下一个文件,使用 args 列出参数,若提供 filelist 则替换当前参数列表并开始编辑第一个文件,若指定 command 则在编辑第一个文件后执行 |
| [address] nu [count] | 打印指定行,并在每行前加上缓冲区行号, # 可作为 number nu 的缩写 |
| [address] o [ /pattern/] | 在指定地址或匹配 pattern 的行进入打开模式,用 Q 退出 |
| P | 保存当前编辑器缓冲区,就像系统崩溃时一样 |
| [address] p [count] | 打印指定行,并打印非打印字符 |
| [address] pu [char] | 从命名缓冲区恢复之前删除或复制的行到指定地址,若未指定 char 则恢复最后删除或复制的文本 |
| q | 终止当前编辑会话,若文件自上次更改后未保存或参数列表中有未访问的文件,需使用 ! 标志才能退出 |
| s [ ! ] [/pattern/rep/ options] [count] | 将指定行中 pattern 的每个实例替换为 repl ,若省略 pattern repl 则重复上次替换,支持 g (替换所有实例)和 c (每次更改前提示确认)选项 |
| [address] r [ ! ] file | 将文件内容复制到指定地址,若未指定文件则使用当前文件名 |
| [address] r ! command | 将命令的输出读入指定地址后的文本中 |
| rec file | 从系统保存区域恢复文件 |
| rew [ ! ] | 倒回参数列表并开始编辑第一个文件, ! 标志不警告未保存的更改 |
| se parameter parameter2 ... | 设置选项的值,若未提供参数则打印所有已更改的选项,布尔值选项可使用 option nooption ,其他选项使用 option=value 语法 |
| sh | 创建新的shell,shell终止后继续编辑 |
| so file | 读取并执行文件中的命令 |
| [address] t destination | 将指定地址的行复制到目标地址 |
| [address] ta tag | 将编辑焦点切换到 tag |
| unabbreviate una word | 从缩写列表中移除单词 |
| undo U | 撤销上一个编辑命令的更改 |
| unmap unm char | 从宏列表中移除 char |
| [address] v /pattern / [commands] | 对不包含 pattern 的所有行执行命令,若未指定命令则打印这些行 |
| ve | 打印编辑器的当前版本号和最后更改日期 |
| [address] vi [type] [count] | 在指定地址进入可视模式,用 Q 退出, type 可以是 - " . count 指定初始窗口大小 |
| [address] w [ ! ] [ [>>] file] | 将指定行写入文件,若未指定地址则写入整个缓冲区内容,若未指定文件则保存到当前文件名, >> file 表示追加到文件末尾, ! 标志强制覆盖文件现有内容 |
| [address] w ! command | 通过管道将指定行写入命令 |
| wq [ ! ] | 保存并退出文件 |
| [address] ya [char] [count] | 将指定行放入名为 char 的缓冲区,若未指定 char 则放入通用缓冲区 |
| [address] z [type] [count] | 打印以指定行为顶部的文本窗口, type 可选, count 指定显示的行数 |
| [address] ! command | 在shell中执行命令,若指定地址,则将地址中的行作为标准输入应用到命令,并将输出替换这些行 |
| [address] = | 打印指定行的行号 |
| [address] < [count] [address] > [count] | 按指定方向移动指定行,左移( < )仅移动空格和制表符 |
| address | 打印指定地址的行 |
| RETURN | 打印文件中的下一行 |
| [address] & [options] [count] | 重复上一个替换命令 |
| [address] - [count] | 用替换命令中的上一个替换模式替换上一个正则表达式 |

mermaid流程图如下:

graph LR
    A[进入ex] --> B[执行命令]
    B --> C{命令类型}
    C --> D[编辑命令]
    C --> E[文件操作命令]
    C --> F[打印命令]
    C --> G[宏命令]
    D --> B[继续执行其他命令]
    E --> B
    F --> B
    G --> B
    B --> H[退出ex]
sed编辑器

sed 编辑器的调用命令为: sed [options] file(s) ,支持以下选项:
| 选项 | 用途 |
| ---- | ---- |
| -n | 仅打印 p 命令指定的行或 s 命令的 p 标志指定的行 |
| -e cmd | 下一个参数是编辑命令 |
| -f file | 下一个参数是包含编辑命令的文件 |

所有 sed 命令的通用形式为: [address] [, address] [ ! ]command [arguments] sed 会将输入的每一行复制到模式空间,指令由地址和编辑命令组成。若命令的地址与模式空间中的行匹配,则对该行执行命令;若命令没有地址,则对每一行输入执行命令。需注意,命令会影响模式空间的内容,后续命令的地址会尝试匹配模式空间中的行,而非原始输入行。

sed 命令中,地址可以是行号或用斜杠括起来的模式( /pattern/ ),指定两个地址时不能混合使用不同类型的地址。模式可使用正则表达式, \n 可匹配模式空间中的换行符,但不包括模式空间末尾的换行符。若未指定模式,命令将应用于所有行;若只指定一个地址,命令将应用于第一个和第二个地址之间的所有行(包括这两行)。 ! 操作符可使 sed 对不包含模式的所有行执行命令。多个命令可通过花括号分组:

[/pattern /] [, /pattern /] {
    command1
    command2
}

以下是 sed 命令的字母顺序列表:
| 命令 | 用途 |
| ---- | ---- |
| : label | 指定一个标签,供 b t 命令跳转,标签最多包含八个字符 |
| b | 若有 [/pattern/]= ,则将匹配模式的每行的行号写入标准输出 |
| [address] a\ text | 在匹配地址的每行后追加文本,若文本跨多行,换行符前需加反斜杠,插入操作在遇到第一个未转义的换行符时结束,结果读入模式空间,编辑列表结束或命令明确打印模式空间时输出到标准输出 |
| [address1] [, address2] b [label] | 跳转到用 : 命令设置的标签,若未指定标签,则跳转到脚本末尾,即跳过后续编辑命令 |
| [address1] [, address2] c\ text | 用文本替换模式空间的内容,文本处理方式与 a 命令相同 |
| [address1] [, address2] d | 删除模式空间中的行,该行不输出到标准输出,读取新的输入行,从编辑列表的第一个命令开始继续编辑 |
| [address1] [, address2] D | 删除由 N 命令创建的多行模式的第一部分(直到嵌入的换行符)并开始编辑,若未对该行应用 N 命令,则与 d 命令相同 |
| [address] [, address2] g | 将保留空间(见 h H 命令)的内容复制到模式空间,覆盖原有内容 |
| [address1] [, address2] G | 将保留空间的内容追加到模式空间的内容之后 |
| [address1] [, address2] h | 将模式空间的内容复制到保留空间,覆盖保留空间的原有内容 |
| [address1] [, address2] H | 将模式空间的内容追加到保留空间的内容之后,新旧内容用换行符分隔 |
| [address1] i\ text | 在匹配地址的每行前插入文本,文本处理方式与 a 命令相同 |
| [address] [, address2] n | 读取下一行输入到模式空间,当前行输出,但控制转移到下一个编辑命令,而非从编辑列表顶部开始 |
| [address1] [, address2] N | 将下一行输入追加到模式空间的内容之后,两行用嵌入的换行符分隔,该命令用于跨两行进行模式匹配 |
| [address1] [, address2] p | 打印指定的行,除非使用 -n 命令行选项,否则该命令会导致输出中该行重复,也用于命令改变控制流( d , N , b )的情况 |
| [address1] [, address2] P | 打印由 N 命令创建的多行模式的第一部分(直到嵌入的换行符),若未对该行应用 N 命令,则与 p 命令相同 |
| [address] q | 遇到指定地址时退出,先将指定行写入输出,并将之前 a r 命令追加的文本一起输出 |
| [address] r file | 读取文件内容并追加到模式空间的内容之后, r 和文件名之间必须有一个空格 |
| [address1] [, address2] s/pattern/replacement/[flags] | 将指定行中的 pattern 替换为 replacement ,若使用模式地址, // 表示最后指定的模式地址。支持以下标志: g (替换每行中 /pattern/ 的所有实例)、 p (成功替换时打印该行)、 w file (替换成功时将该行写入文件,最多可打开十个不同的文件) |
| [address1] [, address2] t [label] | 测试指定行是否有成功的替换,若有则跳转到标签,若未指定标签,则跳到编辑命令列表的底部 |
| [address1] [, address2] w file | 将模式空间的内容写入文件,该操作在遇到命令时执行,而非模式空间输出时, w 和文件名之间必须有一个空格,最多可打开十个不同的文件 |
| [address1] [, address2] x | 交换模式空间和保留空间的内容 |

awk程序

awk 程序由模式和过程组成: pattern {procedure} ,两者都是可选的。若缺少 pattern ,则对所有行应用 {procedure} ;若缺少 {procedure} ,则将行原样输出到标准输出。

每个输入行(记录)会根据空白字符(空格或制表符)或用户定义的记录分隔符分割成字段,字段可通过变量 $1, $2, ..., $n 引用, $0 表示整个记录。

模式可以使用正则表达式,此外还有以下规则:
- BEGIN 模式允许指定在处理第一行输入之前执行的过程,通常用于设置全局变量。
- END 模式指定在处理最后一行输入之后执行的过程。
- ^ $ 可分别引用字段的开头和结尾,而非行的开头和结尾。
- 模式可以是使用关系运算符( < , <= , == , != , >= , > )的关系表达式,比较可以是字符串或数值比较。
- 模式可以使用布尔运算符( || - 或, && - 与, ! - 非)组合。
- 模式可以包含预定义变量,如 NF > 1 可选择包含多个字段的记录。

以下是一些预定义变量:
| 变量 | 用途 |
| ---- | ---- |
| FS | 字段分隔符,默认为空格和制表符 |
| RS | 记录分隔符,默认为换行符 |
| OFS | 输出字段分隔符,默认为空格 |
| ORS | 输出记录分隔符,默认为换行符 |
| NR | 当前记录的编号 |
| NF | 当前记录中的字段数 |
| $0 | 整个输入记录 |
| $1, $2, ..., $n | 当前记录中的第一个、第二个、…、第n个字段,字段由 FS 分隔 |

过程由一个或多个命令、函数或变量赋值组成,用换行符或分号分隔,包含在花括号内。命令可分为以下四类:
- 变量或数组赋值
- 打印命令
- 内置函数
- 控制流命令

以下是 awk 的一些命令总结:
| 命令 | 用途 |
| ---- | ---- |
| for (i=lower; i<=upper; i++) command | 当变量 i 的值在 lower upper 之间时,执行命令,一系列命令需放在花括号内,可使用 <= 或其他关系运算符, ++ -- 可用于变量增减 |
| for i in array command | 对于数组 array 中的每个变量 i ,执行命令,一系列命令需放在花括号内 |
| if (condition) command [else] [command] | 若条件为真,则执行命令,否则执行 else 子句中的命令,条件可以是使用关系运算符或模式匹配运算符的表达式,一系列命令需放在花括号内 |
| x = length(arg) | 返回 arg 的长度,若未提供 arg ,则默认为 $0 |
| x = log(arg) | 返回 arg 的对数 |
| print [args] | 在输出中打印参数,参数通常是一个或多个字段,也可以是预定义变量,文字字符串需用引号括起来,参数在参数列表中用逗号分隔时,输出中用 OFS 指定的字符分隔,用空格分隔时则直接连接 |
| printf "format, "expression(s) | 格式化打印语句,根据 format 参数的指令格式化字段或变量,参数数量必须与 format 部分指定的数量一致,格式遵循C语言的 printf 语句约定,可包含转义序列,若有多个表达式要打印,需指定多个格式 |
| x = split(string, array [, sep]) | 将字符串 string 按分隔符 sep 分割成数组 array 的元素,若未指定 sep ,则使用 FS ,返回创建的数组元素数量 |
| x = sprintf("format", expression) | 根据指定的格式返回表达式的值 |
| x = sqrt(arg) | 返回 arg 的平方根 |
| x = substr(string,m, [n]) | 返回字符串 string 从第 m 个字符开始的子字符串,若指定 n ,则包含接下来的 n 个字符,若未指定 n ,则包含到字符串末尾的所有字符 |
| while (condition) command | 当条件为真时执行命令,条件的允许情况与 if 命令相同,一系列命令需放在花括号内 |

mermaid流程图如下:

graph LR
    A[开始] --> B[读取输入行]
    B --> C{匹配模式?}
    C -->|是| D[执行过程]
    C -->|否| B[读取下一行]
    D --> B[读取下一行]
    B --> E{是否最后一行?}
    E -->|否| B[继续读取]
    E -->|是| F[结束]

综上所述,掌握这些UNIX文本处理工具和命令,能够帮助用户更高效地进行文本编辑、处理和文档制作,满足不同场景下的需求。通过合理运用这些工具,可大大提高工作效率和质量。

考虑柔性负荷的综合能源系统低碳经济优化调度【考虑碳交易机制】(Matlab代码实现)内容概要:本文围绕“考虑柔性负荷的综合能源系统低碳经济优化调度”展开,重点研究在碳交易机制下如何实现综合能源系统的低碳化与经济性协同优化。通过构建包含风电、光伏、储能、柔性负荷等多种能源形式的系统模型,结合碳交易成本与能源调度成本,提出优化调度策略,以降低碳排放并提升系统运行经济性。文中采用Matlab进行仿真代码实现,验证了所提模型在平衡能源供需、平抑可再生能源波动、引导柔性负荷参与调度等方面的有效性,为低碳能源系统的设计与运行提供了技术支撑。; 适合人群:具备一定电力系统、能源系统背景,熟悉Matlab编程,从事能源优化、低碳调度、综合能源系统等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究碳交易机制对综合能源系统调度决策的影响;②实现柔性负荷在削峰填谷、促进可再生能源消纳中的作用;③掌握基于Matlab的能源系统建模与优化求解方法;④为实际综合能源项目提供低碳经济调度方案参考。; 阅读建议:建议读者结合Matlab代码深入理解模型构建与求解过程,重点关注目标函数设计、约束条件设置及碳交易成本的量化方式,可进一步扩展至多能互补、需求响应等场景进行二次开发与仿真验证。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值