ssss 1 2 3 3 4 45

【sed 用户手册翻译】: 3 sed scrpts

这是对sed用户手册的翻译,有翻译不正确的地方请指出

https://www.gnu.org/software/sed/manual/sed.html

第三章 sed 脚本

  • 3.1 sed 脚本介绍
  • 3.2 sed 命令摘要
  • 3.3 命令 s
  • 3.4 常用命令
  • 3.5 不常用命令
  • 3.6 大师级命令
  • 3.7 GNU sed的专有命令
  • 3.8 多命令语法

3.1 sed 脚本介绍

sed 程序是由一个或多个sed命令构成的。
这些命令可以通过一个或多个 -e, -f, --expression和 --file 选项传入,
如果没有使用以上这些选项,就通过第一个非选项参数传入。
本文里所说的sed脚本 包括所有的通过脚本 或脚本 文件传的脚本 。(查看介绍

sed 命令遵守下面的语法:
[addr]X[options]
X 是一个单个字母的sed命令。
[addr]是一个可选 的行地址。
如果 [addr]被 指定 , 命令X将只会在匹配的行上运行。
[addr]可以是一个指定行的数字 ,可以是一个正刚表达式, 或也可以是行区间。
[options]只对部分的sed命令使用。

下面的例子删除第输入的的30到35行,30,35是个地址区间, d是一个删除命令:
sed '30,35d' input.txt > output.txt

下面的例子打印所有的输入直到 以'foo'开头的行为止。
如果匹配到这样的行,sed会以返回码42退出运行。
如果不能匹配到这样的行(),sed会以返回码0 退出。
/^foo/是一个正则表达式地址,q是退出命令, 42是命令参数
sed '/^foo/q42' input.txt > output.txt

脚本或脚本文件里的命令可以使用冒号(;)或换行符进行分隔。
之个脚本 可以用不用-e 或-f选项指定。

下面的例子都是等价的。
它们展示了两个操作: 删除所有匹配正则表达式/^foo/的行, 使用'world'替换所有出现的'hello'
sed '/^foo/d ; s/hello/world/' input.txt > output.txt
sed -e '/^foo/d' -e 's/hello/world/' input.txt > output.txt
echo '/^foo/d' > script.sed
echo 's/hello/world/' >> script.sed
sed -f script.sed input.txt > output.txt
echo 's/hello/world/' > script2.sed
sed -e '/^foo/d' -f script2.sed input.txt > output.txt

因为语法的原因,命令 a,c,i,后面不能跟冒号。因此他们应该以换行符结尾或被 放在脚本/脚本文件的结尾。

命令前面也可以插入空格。

3.2 sed 命令摘要

GNU sed 支持下面的命令,
其中一些是POSIX标准命令,一些是GNU 扩展命令。
关于这些命令的细节和实例在后面的章节里。
用括号( () )包起来的是助记的内容。

a\

text
把 text追加到行的后面

a text

把 text追加到行的后面(另一种语法形式)

b lable

无条件跳转到lable
lable 可以被忽略, 在这种情况下,直接 开始下一个循环

c \

text
用text 替换行

c text

用text 替换行

d

把模式空间的内容删除,立即开始下一下循环

D

如果 模式空间里包含换行符, 把模式空间里的第一个换行符前面的内容删除, 并以当下的模式空间(里的内容)重新开始新的循环,并不从输入中读取一个新行。
如果 模式空间里没有换行符, 就像命令d一样,开始一个新的循环。

e

执行在模式空间里的命令, 并用输出 替换模式空间,
换行符会被删除

e command

执行给定的命令,并把它的输出输出到输出 流。
这个命令可以写在多行,但是最后要以反斜杠结尾

F

打印当前文件的文件名(带有换行符)

g

使用驻留空间里的内容替换模式空间的内容

G

在模式空间的内容后面追加一个换行符, 然后把驻留空间的内容追加到模式空间内容后面。

h

使用模式空间的内容 替换 驻留空间里的内容

H

在驻留空间的内容后面追加一个换行符, 然后把模式空间的内容追加到驻留空间的内容后面

i\

text
在一行之前插入text

i text

在一行之前插入text

l

明确的 打印模式空间的内容

n

如果禁止自动打印,打印出模式空间的内容,然后, 使用输入流的下一行替换当前模式空间。
如果输入流已经为空(没有别的输入/到结尾),sed不执行别的命令,直接退出

N

在模式空间加入一个换行符,然后在把输入流的下一行,追加在模式空间。
如果输入流已经为空(没有别的输入/到结尾),sed不执行别的命令,直接退出

p

打印模式空间

P

打印模式空间第一个换行符前面的内容

q[exit-code]

sed不执行别的命令,直接退出

Q[exit-code]

q命令一样, 但是他不会打印模式空间里的内容。  

他提供 了一个返回退出代码 给他的调用 者的方法。

r filename

读文件的文件名

R filename

把读入的文件名进行缓存,并在循环结束或读入下一行时,把它插入到输出 流

s/regexp/replacement/[flags]

(替换)使用正则表达 式对模式空间里的内容进行匹配,如果匹配成功,使用replacement 进行替换

t lable

(测试)如果 从上一行被读入开始,发生了成功的替换,或选择条件分支,跳转到lable,
lable 可以被忽略, 在这种情况下,直接开始下一个循环

T lable

(测试)如果 从上一行被读入开始,没有发生了成功的替换,或选择条件分支,跳转到lable,
lable 可以被忽略, 在这种情况下,直接开始下一个循环

v [version]

(版本)这个命令不做任何事,但是如果sed不支持 GNU sed 扩展 或 指定的版本不可用,会产生失败。

w filename

把模式空间的内容写到(filename指定的)文件里去

W filename

把模式空间第一个换行符前的部分写到(filename指定的)文件里去

x

交换模式空间跟驻留空间的内容

y/src/dst/

把模式空间里任何匹配 source-char 的字符转换成 dest-chars里的对应字符

z

这个命令清空模式空间的内容

#

注释,直到下一个换行符

把多条命令组合在一起

=

打印当下输入行的行号(带一个换行符)

:lable

为跳转命令(b, t, T)指定label 的位置

3.3 命令 s

s命令也许是sed里最重要的一个命令,它还有很多不同的选项可以设定。
s 命令的语法是:
s/regexp/replacement/flags

它基本的概念非常简单: s 命令试图在模式空间里使用提供的正则表达试进行匹配。 如果匹配成功,模式空间里被匹配到的部分就会被 replacement替换掉

关于正则表达式的语法请参考 正则表达式定位

replacement 里可以包含 \n (n是一个1-9的数字),表示模式空间里被匹配到的第n个 \(和匹配的\)之间的内容
replacement 里可以包含 & 字符,表示模式空间里整个被匹配的部分。

/ 字符可以被 s命令的任何单字符 替换。
/ 字符(或其它 可转义字符)仅当它前面有一个\字符的时候 可以出现在 regexp 或replacement

最后, 作为GNUsed扩展的一部分, 你可以使用用返斜杠和这些字母(L,l,U,u,E)组成的特别字符串。
他们的含义如下:

  • \L
    把replacement 转成小写 直到\U , 或\E

  • \l
    把下一个字母转换成小写

  • \U
    把replacement 转成大写 直到\L 或 \E

  • \u
    把一下个字母转成大写

  • \E
    停止由\L 或 \U开始的字符转换

当使用了 flag g, 字符转换并不从一个正则匹配传导到下一个。
例如下面的例子中的命令在模式空间的'a-b-'上运行:
s/\(b\?\)-/x\u\1/g
输出 会是 'axxB'.
当对第一个'-'进行替换时, '\u'只会影响【When replacing the first ‘-’, the ‘\u’ sequence only affects the empty replacement of ‘\1’】,它并不影响 用xB替换b- 加入到模式空间的x 字符,

然而,如果 他们后面跟着空替换\l 跟 \u会影响替换串里的剩余部分。
模式空间里是 'a-b-',运行下面的命令:
s/\(b\?\)-/\u\1x/g
会使用'X'替换 '-', 'Bx'替换‘b-'.
如果 这样的行为不是你期望的, 你可以通过 (在'\1'后面)加入一个'\E'来阻止。

要想在最终的替换字符串里加入字符 \ , & 或 换行符, 要在他们之前加入一个 \

s命令的flags

s命令后面可以跟上零个或多个下在的flags:

  • g
    把替换应用到所有的正则表达式匹配上,不仅仅是第一个上面

  • number
    只替换第number个匹配。
    注意:POSIX标准并没有指定 g 跟 number 同时使用会发生什么。当下也没有在已经 存在 的sed 实现里形成广泛的共识。对于GNU sed , 是这样定义的:忽略第number个匹配前面的,对之后的所有匹配进行替换(包括第number个本身)

  • p
    如果 发生了替换,打印新的模式空间内容
    注意: 如果p和e选项同时指定 ,他们的相对顺序会产生不同的结果 。通常, ep是你想要的。但是其它的方式 可以对 调试非常有帮助。 因此,以当下的GNU sed 版本里,当p选项同时在e的前面还是后面出现,会在估计的前后都 打印模式空间的内容。然而,s命令一般的flags。只会产生一次影响。仅管这个行为写在了文档里。但是以后可能会发生变化。

  • w filename
    如果 发生了替换,把结果 写进指定的文件 里。做为GNU sed的一个扩展, 支持下面两个特别的文件名:
    /dev/stderr: 把结果 写进标准错误输出
    /dev/stdout:把结果 写进标准输出

  • e
    这个命令允许把输入从一个shell 命令的导到模式空间。
    如果 替换发生,在模式空间的命令会被执行,并且模式空间会被 他的输出替换。后面会加上一个换行符。如果 执行的命令中含有NUL 字符,结果会是非定义 的。(这是一个GNU sed扩展)

  • I

  • i
    正则表达式的 I 修饰符 是一个GNU扩展。它使的sed 通过 字符大小写无关的方式对 regexp进行匹配。

M

m

正则表达式的M 修饰符 是一个GNU 扩展。它使 GNU sed 在多行模式下 进行正则表达式匹配。
这个修饰符会使 ^ 和 $ 分别匹配 (相对于 正常行为) 换行符后的空字串和 换行符前的空字串。
有两个特别的字符串(`和 ')跟 buffer的 开始与结尾匹配。
在多行模式下,period character(.)并不跟换行符进行匹配。

3.4 常用命令

既然你使用了sed, 你一定非常想知道 下面这些命令:

#

[不可以使用定位]

字符 是注释的开始;注释一直持续到换行符。

如果你关注可移植性, 你需要知道是 sed的一些实现(不符合POSIX的) 可能只支持 单行注释,并且 只有脚本的第一个字符是#.

注意: 如果 sed 脚本的前两个字符是#n, 那么 -n 选项 是强制的。如果 你想在脚本 的第一行放置注释,并且 注释以字符n开始,而你并不希望它是这样的行为, 那么请确保你使用大写字符 "N" 或, 在'n'前面加入只少一个空格符。

q [exit-code]

停止处理命令和输入, 退出sed。
例子:在打印出第二行后退出:

$ seq 3 | sed 2q
1
2

这个命令只接收一个地址。 注意,如果自动打印没有被-n选项关闭, 当前模式空间会被 打印出来。
从sed脚本返回一个退出代码的功能 是GNUsed 的扩展。

同时请参考 GNU sed扩展Q命令,它会在不打印当下模式空间内容的情况 下退出。

d

删除模式空间的内容;立即开始下一个工作循环。
例子: 删除第二个输入行:

$ seq 3 | sed 2d
1
3

p

打印出模式空间(到标准输出)。这个命令通常跟 -n选项连起来使用
例子: 只打印第二行:

$ seq 3 | sed -n 2p
2

n

如果自动打印没有被禁止, 打印模式空间, 然后 使用下一个输入行替换模式空间的内容。如果没有输入那么不再处理其余的命令退出sed.
这个命令用来跳过一些行,非常有效(比如:每N 行处理)
例子:每3 行执行替换操作( 两个n 命令跳过两行):

$ seq 6 | sed 'n;n;s/./x/'
1
2
x
4
5
x

GNU sed 提供了一个扩展的定位语法(first~step)可以达到相同的结果 :

$ seq 6 | sed '0~3s/./x/'
1
2
x
4
5
x

一组命令被 包在{和}之间。在你想对一个匹配的地址执行一组的命令时, 这个语法尤为有用。
例子: 对第二行进行替换后,打印:

$ seq 3 | sed -n '2{s/2/X/ ; p}'
X

3.5 不常用命令

尽管下面的命令也许相比前面一节里的命令使用频率并不高, 然而使用这些命令可以生成一些 非常小但很有用的sed 脚本。

3.6 大师级命令

3.7 GNU sed的专有命令

3.8 多命令语法

在sed 程序里 有很多种方法来指定多命令。
当从一个文件(使用-f 选项)里运行一个sed 脚本,使用换行符是最常见的。
在命令行中, 所有的sed 命令可以使用 换行符被分隔。 另一种方法是 把命令当做 -e 选项的参数:

$ seq 6 | sed '1d  
3d  
5d'  
2  
4  
6  
  
$ seq 6 | sed -e 1d -e 3d -e 5d  
2  
4  
6  

分号(';')可以被 用来分隔大部分的命令:

$ seq 6 | sed '1d;3d;5d'  
2  
4  
6  

{}, b,t,T: 这些命令可以使用分号进行分隔开 (这是一个不可移植 的GNU SED 扩展)

$ seq 4 | sed '{1d;3d}'  
2  
4  
  
$ seq 6 | sed '{1d;3d};5d'  
2  
4  
6  

标签(使用在b,t,T命令里的): 命令可以读到分号。 前导和后缀的空字符可以被忽略。
在下面的例子里, 标准是'x'. 第一个例子可以在GNU sed上面运行。第二个是等价的,一个可移植的。
关于跳转和标签 请参考跳转和流程控制

$ seq 3 | sed '/1/b x ; s/^/=/ ; :x ; 3d'  
1  
=2  
  
$ seq 3 | sed -e '/1/bx' -e 's/^/=/' -e ':x' -e '3d'  
1  
=2  

3.8.1 需要换行符的命令

下面的命令不能使用分号把他们跟别的命令进行分隔开,而是需要换行符来进行分隔。

a,c,i (追加/改变/插入)

跟在a,c,i 命令后面的所有字符 都被 看做是要 追加/改变/插入 的内容。使用分号会导致 非预期的结果 :

$ seq 2 | sed '1aHello ; 2d'   
1  
Hello ; 2d  
2  

使用 -e 或分隔符把命令分隔开:

$ seq 2 | sed -e 1aHello -e 2d
1
Hello

$ seq 2 | sed '1aHello
2d'
1
Hello  

注意: 在a,c,i后的紧跟着指定要添加的文本是GNU sed的扩展。
下面是一种可以移植, 兼容 POSIX的做法:

$ seq 2 | sed '1a\
Hello
2d'
1
Hello
# (comment)

所有跟在‘#’后面直到第一个换行符的字符都会被 忽略掉:

$ seq 3 | sed '# this is a comment ; 2d'  
1  
2  
3  


$ seq 3 | sed '# this is a comment  
2d'  
1  
3  
r,R,w,W (reading and writing files)

r,R,w,W会在之后的文本中解释文件名,直到碰到换行符。
如果碰到空格, 注释,或分号, 他们也会被 包含进文件名中, 导致 非预期 的结果:

$ seq 2 | sed '1w hello.txt ; 2d'  
1  
2  

$ ls -log  
total 4  
-rw-rw-r-- 1 2 Jan 23 23:03 hello.txt ; 2d  
  
$ cat 'hello.txt ; 2d'  
1  

注意:默认情况下,sed会忽略 r,R,w,W命令产生的读写错误(比如找不到文件)。
在下面的命令里,sed尝试去读取一个名为“hello.txt ; N”的文件。 这个文件是不存在的,这个错误被直接忽略掉了:

$ echo x | sed '1rhello.txt ; N'    
x   
e (command execution)

跟在e 命令后面直到碰到新行的所有字符 都会被发送到shell.

如果碰到空格, 注释,或分号, 他们也会被 包含进shell命令里, 导致 非预期 的结果:

$ echo a | sed '1e touch foo#bar'  
a  
  
$ ls -1  
foo#bar  
  
$ echo a | sed '1e touch foo ; s/a/b/'  
sh: 1: s/a/b/: not found  
a   
s///[we] (substitute with e or w flags)

在替换命令里,w 标志符把替换结果 琯进一个文件, e 标志符把替换结果当成一个shell 命令来执行。
像r/R/w/W/e命令一样, 他们需要 以一个换行符来结尾。

如果碰到空格, 注释,或分号, 他们也会被 包含进shell命令或文件名里, 导致 非预期 的结果:

$ echo a | sed 's/a/b/w1.txt#foo'  
b  
  
$ ls -1  
1.txt#foo  
posted @   会游泳的骆驼  阅读(60)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
百度 123

没有一个人在这个世上独活。

点击右上角即可分享
微信分享提示