曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 3691|回复: 1
打印 上一主题 下一主题

G 与 h 命令

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2012-2-3 01:45:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
G 命令将 hold space 里的内容追加到 pattern space 中。前后的内容由换行符(\n)隔开。

测试文本
[beyes@beyes   sed]$ cat test.txt
hello world
hello linux
hello unix
hello groad

下面将仅用 G 命令来操作该文本,看下会发生情况:
[beyes@beyes   sed]$ sed 'G' test.txt
hello world

hello linux

hello unix

hello groad
由输出可见,每行被一个空行隔开了。命令的处理流程是:sed 先读入第一行内容到 pattern space ,然后将 hold space 里的内容追加到 pattern space 中,因为此时 hold space 中的内容为空,因此执行 'G' 命令后 pattern space 里的内容为:hello world\n(空行) 。此后反复这样的做法,最后便能看到如上的输出。

h 命令复制 pattern space 中的内容到 hold space 中。

下面将利用 G 命令和 h 命令反序输出上面测试文本内容,其效果如同 tac 命令,如:
[beyes@beyes   sed]$ tac test.txt
hello groad
hello unix
hello linux
hello world

命令如下:
[beyes@beyes   sed]$ sed -n '1!G;h;$p' test.txt
hello groad
hello unix
hello linux
hello world

上面第一个命令 '1!G' 表示如果不是第一行内容那么就将该行追加到 pattern space 中。

从头开始看处理流程:
首先,sed 会读入第一行内容到 pattern space 中,由于是处理第一行,所以 G 命令不会被执行;接着使用 h 命令将 pattern space 中的第一行内容复制到 hold space 中。在第二轮处理时,读入第 2 行内容到 pattern space 中,此时 G 命令会得到执行,结果是 hold space 中的第 1 行内容会被追加到 pattern space 中,这样 pattern space 中的内容就是:
第 2 行
第 1 行

形成了反向排序。然后,这两行内容同样会由 h 命令复制到 hold space 中。

以后的处理就是按照上述规律循环进行,直到最后到达最后一行时,$p 命令得到执行,此时打印出所有 pattern space 中的内容,于是可以看到上面文本的反序输出。

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
沙发
 楼主| 发表于 2013-3-15 23:04:50 | 只看该作者

实例1

如何用 sed 过滤  echo -e 'one\\ntwo\\nthree ,使获得:
one
three
的输出?
可能会尝试:
echo -e 'one\\ntwo\\nthree' | sed -n 's/one\\ntwo/one/p'
但这不会有任何结果。为什么?

echo 里使用 -e 参数后,就开启了它对转义字符的解析功能,于是 '\\n' 会被认为是个”换行“,所以 one\\ntwo\\nthree 就被解析为:
one
two
three

当这 3 行字串通过管道符流向 sed 时,sed 是一行一行的处理的,并且不会读入换行符。因此,如果非得用 sed 来达到上述的输出结果,可以尝试使用下面的方法:
$ echo -e 'one\\ntwo\\nthree' | sed -n '1h;1!H;${g;s/one.*two/one/p}'
one
three
现在对 sed 中的命令逐个分析:
1h ,表示的是,如果是第 1 行,那么将 pattern space 中的内容复制到 hold space ,也就是当处理 one 这一行时,one 这个字串会被复制到 hold space 中。自然的,该命令只会执行一次。
1!H ,表示的是,除了第 1 行外,其后被读入到 patter space 中的行都要追加到 hold space 中,并且每一行都会有一个 '\\n' 隔开。这种追加的行为会直到处理到最后一行才结束,也就是说到最后 hold space 中的内容就是:
one\\n\\two\\nthree 。从这个角度上来看,上述的几个命令的行为,实际上是还原了原来要处理的内容原貌。

当 sed 处理到最后一行时,即匹配 $ 时,就会接着执行 {g;s/one.*two/one/p} 这个命令组。
g 命令做的工作是,将 hold space 中的内容搬到 pattern space 中。当这个工作做完后,就执行 s/one.*two/one/ 这个替换工作,替换的结果就是将 one\\ntwo 替换成 one (其实 .* 在这里可以就用一个 . 来表示即可)。
最后使用 p 命令将被处理过的内容打印了出来。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-15 14:11 , Processed in 0.065042 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表