sed 快速参考

这里的内容大部份摘自 UNIX超级工具。

sed的操作方式如下

每行输入都会被复制到模式空间中

可以直接在命令行中输入编辑命令(多个命令请加-e选项)。 也可以用-f选项来从脚本文件里得到编辑命令。所有的编辑命令都会按照文本的 输入顺序作用于各行。

编辑命令会作用于所有的行(全局),除非用行寻址限定了命令所作用的行。

如果一个命令更改了输入,那么后续的命令地址就会作用于模式空间中当前行, 而不是原始输入行。

原始输入文件不会被更改,编辑命令修改的是原始文件输入行的副本。 除非使用-n选项,否则该副本会被 发送到标准输出。你可能需要重定向到一个 文件。(但是别重定向到同一个文件,那样你的文件就被清空了!)

sed命令的语法

sed命令有通用的格式:

[address][,address][!]command[arguments]

sed命令一般包含地址address和编辑命令command. command包括单个字母或符号.arguments包括用于b或t的标签, 用于r或w的文件名、用于s的替换标志."[something]"表示可选项.

在sed中,大括号({})用于把一个地址嵌套在另一个地址内空,或在相同的地址 上应用多个命令.可以用多行分隔命令,或者用";".

模式寻址

一个sed命令可以指定0-2个地址. 这个地址可以是行号、符号$(表示最后一行)或者是包含在斜杠内的正则表达 式. 除此之外,\n可以用来匹配模式空间中换行符(由N命令产生),但是不能 匹配模式空间末尾的换行符.

sed命令概要

# 在sed脚本中开始一个注释行.如果第一个注释行确切为#n,说明sed设置了命令行选项-n
: :label 给脚本的一行加上标签,以便使用命令b或t进行转移控制.参数label最多可包含7个字符.
= [address]= 把每一行的行号写到标准输出.
a [address]a\\\\n text 在匹配行后面添加文本.text可以包含多行,但换行符需要用\\隐藏起来.
b [address1][,address2]b[label] 无条件转移到标签,默认转到脚本末尾.
c [address1][,address2]c\\\\n text 用文本替换地址所选择的行.如果指定了行的范围,那么所有的行会被作为一组被单个的文本替换.同a命令,文本的换行符需要隐藏起来
d [address1][,address2]d 删去匹配的行,因而不会发送到标准输出
D [address1][,address2]D 删去由命令N所创建的模式空间中的多行文本的第一部分(一起到插入的换行符为止),并脚本中的第一个命令恢复编辑.如果该命令清空了模式空间,那么就会读取一行新的输入,如同执行了命令d一样.
g [address1][,address2]g 把保留空间中内容粘贴到模式空间中,清除模式空间中原来的内容.
G [address1][,address2]G 同g功能相同,但是是追加到模式空间中.
h [address1][,address2]h 把模式空间中内容复制到保留空间中.
H [address1][,address2]H 把模式空间中内容追加到保留空间中.
i [address]i\\\\n text 在先前插入文本,参考a.
n [address1][,address2]n 把下一行读入到模式空间中.当前行发送到标准输出,下一行将成为当前行.控制将转移给n后面的所跟的命令,而不是回到脚本的开始处.
N [address1][,address2]N 把下一个输入行添加到模式空间的内容之后;这现行文本用一个插入的换行符分开.(该命令允许跨越两行进行模式匹配.)如果用\\n来匹插入的换行符,那么可以跨越多行进行模式匹配.
p [address1][,address2]p 打印行,除非使用了命令行选项-n,否则这命令将导致输出相同的行.另外它常用于那些用于改变流控制的命令之前,并可能输出当前行.
P [address1][,address2]P 打印由命令N创建的多行模式的第一部分(一直到插入的换行符为止).如果没有应用命令N, 那么该命令的作用与p相同.
q [address]q 退出
r [address]r file 读取文件内容,并把它添加到模式空间的内容后面.命令r和文件之间必须刚好一个空格.
s [address1][,address2]s /pattern/replacement/[flags] 替换.flags可以为n(数字,指匹配的第n个),g,p, w file.
t [address1][,address2]t[label] 测试是否在寻址到的行上完成了任何替换,如果是将控制转移到标签,默认标签为脚本尾.
w [address1][,address2]w file 把模式空间中内容添加到文件中.遇到此命令即发生动作.w与file之间必须刚好一个空格.一次最多能打开10个文件.如果文件不存在,会创建之.存在, 每次执行该命令时,它都会被重写一次.但多个直接输出到同一个文件的命令会在文件末尾进行追加.
x [address1][,address2]x 交换保留空间与模式空间中内容.
y [address1][,address2]y/abc/xyz/ 转换字符.a->x,b->y,c->z.

Example

#!/bin/sh
# cgrep - 使用sed的多行上下文grep
# 用法:cgrep [-context] pattern [file ...]

n=3
case $1 in -[1-9]*)
n=`expr 1-"$1"`
shift
esac
re=$(1?);shift

sed -n "
1b start
: top
\~$re~{
  h;n;p;H;g
  b endif
}
  N
  : start
  \~$re~{ = ; p;}
: endif
$n,\$D
b top
" "$@"

LaTeX tips: 章节样式

节是用 \@startsection{name}{level}{indent}{beforeskip}{afterskip}{style} 定义的.

indent 如果是正的,标题文本就会都有这样的 left-skip ;负的,则标题文本起始于外页边.

beforeskip 的绝对值为标题文本与上页的距离.正负号控制首段是否缩进.

afterskip 为标题文本也后续文本间距离,小于零时,可以得到接排的效果.

style 为标题文本的样式.可以在这里使用一些格式控制得到特殊的标题效果.

如: \hrule\medskip\raggedleft\itshape 或如: \centering\itshape

这是个例子:

\renewcommand{\subsection}{\@startsection
{subsection}{2}{0mm}{-\baselineskip}%
{.5\baselineskip}%
{\normalfont\normalsize\itshape}}

章和部是用 \secdef 定义的,定义形如:

\recommand{\part}{...\secdef\cmda\cmdb}
\newcommand{\cmda}[2][default]{...}
\newcommand{\cmdb}[1]{...}

LaTeX tips: 页面样式

在 Latex 里可以利用 fancyhdr 修改页面样式,也就是页眉,页脚.

这个宏包很方便.它将页眉,页脚分成左,中,右三部分, 还分为奇数页和偶数页两种情况.

其实对一些简单的情况,我们可以自己定义页面样式.

在 Latex 里, 是用 ps@page_style_name 的方式来调用,定义页面样式. 我们只要定义一个命令 ps@page_style_name, 在这个命令里设置好页眉,页脚即可. 这里举例:

\newcommand{\ps@mystyle}{%
  \renewcommand{\@oddhead}{Latex\hfil\textrm{\thepage}\hfil{}}%
  \renewcommand{\@evenhead}{{}\hfil\textrm{\thepage}\hfil Pagestyle}%
  \renewcommand{\@oddfoot}{}%
  \renewcommand{\@evenfoot}{}%
}

如果在页眉或页脚里含有章节信息,就要使用 mark 了. 在 TeXbook 里有一个很好的例子. 要用到 \lastmark \topmark \firstmark 之类的东西.

我们在 Latex 里只要利用 \leftmark \rightmark 即可. 这两个 mark 由 \chaptermark \sectionmark 之类的东西设置. 如果不满意可以自己将它改了.它带有一个章节标题的参数. 在重定义这些命令时你可能要用到 \markboth.

LaTeX package: GraphicxSP

GraphicxSP is an extension of the graphicx package. GraphicxSP embeds the graphic in the PDF document once, and allows the document author to use and re-use that same graphic without significantly increasing the file size. Additionally, GraphicxSP supports Adobe transparency imaging model.

LaTeX tips: 计数器重置

可以利用 \@addtoreset 将一个计数器加到另一个计算器, 使得第二个被增量及重置时第一个计数器会重置为 0. 但从计数器的重置列解除重置要麻烦一些:
\makeatletter
\def\rmreset#1#2{%
 \begingroup
 \def\@elt##1{%
   \expandafter\ifx\csname c@#1\expandafter\endcsname\csname c@##1\endcsname
   \else\noexpand\@elt{##1}\fi
 }
 \expandafter\xdef\csname cl@#2\endcsname{\csname cl@#2\endcsname}%
 \endgroup
}%
\makeatother
然后, 比如, 你可以这样用: \rmreset{subsection}{section}

LaTeX tips: \tracingmacros

如果想修改一些宏,但又不记起原来是怎么定义的时候,这就特别有用. 最好在你想修改的前面用 \tracingmacros=1, 而在后面用 \tracingmacros=0 以免输出太多.

LaTeX package: multido

提供 \multido, 方便实现循环. 使用语法 \multido{ variables }{ repetitions }{ stuff }
\begin{picture}(8,1)(0,-.5)
 \put(0,0){\vector(1,0){8}}
 \multido{\i=0+1,\n=0+0.25}{8}{%
   \put(\i,-.1){\line(0,1){.2}}
   \put(\i,-.2){\makebox(0,0)[t]{\n}}}
\end{picture}
\multido{}{10}{\TeX}
\multido{\d=2pt+3pt}{5}{\d, }
\multido{\n=2+3}{10}{\n, }
\multido{\i=2+-3}{10}{\i, }
\multido{\r=2+.305}{6}{\r, }
\multido{\n=2.00+-3.05}{8}{\n, }