mirror of
https://github.com/LCTT/TranslateProject.git
synced 2024-12-23 21:20:42 +08:00
PRF:20180615 Complete Sed Command Guide [Explained with Practical Examples].md
校对部分
This commit is contained in:
parent
83f71117c6
commit
a38741c0cf
@ -271,7 +271,7 @@ Sed 允许在一个块中使用花括号 `{…}` 组合命令。你可以利用
|
||||
|
||||
```
|
||||
sed -n -e '/usb/{
|
||||
/daemon/p
|
||||
/daemon/p
|
||||
}' inputfile
|
||||
|
||||
sed -n -e '/usb.*daemon/p' inputfile
|
||||
@ -311,8 +311,8 @@ sed -e '5q' inputfile
|
||||
sed -n -e '5p' -e '5q' inputfile
|
||||
|
||||
sed -n -e '
|
||||
5p
|
||||
5q
|
||||
5p
|
||||
5q
|
||||
' inputfile
|
||||
|
||||
sed -n -e '5p;5q' inputfile
|
||||
@ -323,8 +323,8 @@ sed -n -e '5p;5q' inputfile
|
||||
```
|
||||
# 组合命令
|
||||
sed -e '5{
|
||||
p
|
||||
q
|
||||
p
|
||||
q
|
||||
}' inputfile
|
||||
|
||||
# 可以简写为:
|
||||
@ -336,272 +336,241 @@ sed '5{p;q}' inputfile
|
||||
|
||||
### 替换命令
|
||||
|
||||
你可以将替换命令想像为 Sed 的“查找替换”功能,这个功能在大多数的“所见即所得”的编辑器上都能找到。Sed 的替换命令与之类似,但比它们更强大。替换命令是 Sed 中最著名的命令之一,在网上有大量的关于这个命令的文档。
|
||||
你可以将替换命令(`s`)想像为 Sed 的“查找替换”功能,这个功能在大多数的“所见即所得”的编辑器上都能找到。Sed 的替换命令与之类似,但比它们更强大。替换命令是 Sed 中最著名的命令之一,在网上有大量的关于这个命令的文档。
|
||||
|
||||
![The Sed `substitution` command][19]
|
||||
|
||||
[在前一篇文章][20]中我们已经讲过它了,因此,在这里就不再重复了。但是,如果你对它的使用不是很熟悉,那么你需要记住下面的这些关键点:
|
||||
|
||||
* 替换命令有两个参数:查找模式和替换字符串:`sed s/:/-----/ inputfile`
|
||||
|
||||
* 命令和它的参数是用任意一个字符来分隔的。这主要看你的习惯,在 99% 的时间中我都使用斜杠,但也会用其它的字符:`sed s%:%-----% inputfile`、`sed sX:X-----X inputfile` 或者甚至是 `sed 's : ----- ' inputfile`
|
||||
|
||||
* 默认情况下,替换命令仅被应用到模式空间中匹配到的第一个字符串上。你可以通过在命令之后指定一个匹配指数作为标志来改变这种情况:`sed 's/:/-----/1' inputfile`、`sed 's/:/-----/2' inputfile`、`sed 's/:/-----/3' inputfile`、…
|
||||
|
||||
* 如果你想执行一个全面的替换(即:在模式空间上的每个非重叠匹配),你需要增加 `g` 标志:`sed 's/:/-----/g' inputfile`
|
||||
|
||||
* 在字符串替换中,出现的任何一个 `&` 符号都将被与查找模式匹配的子字符串替换:`sed 's/:/-&&&-/g' inputfile`、`sed 's/…./& /g' inputfile`
|
||||
|
||||
* 圆括号(在扩展的正则表达式中的 `(…)` 或者基本的正则表达式中的 `\(…\)`)被引用为捕获组。那是匹配字符串的一部分,可以在替换字符串中被引用。`\1` 是第一个捕获组的内容,`\2` 是第二个捕获组的内容,依次类推:`sed -E 's/(.)(.)/\2\1/g' inputfile`、`sed -E 's/(.):x:(.):(.*)/\1:\3/' inputfile`(后者之所能正常工作是因为 [正则表达式中的量词星号表示重复匹配下去,直到不匹配为止][21],并且它可以匹配许多个字符)
|
||||
|
||||
* 在查找模式或替换字符串时,你可以通过使用一个反斜杠来去除任何字符的特殊意义:`sed 's/:/--\&--/g' inputfile`,`sed 's/\//\\/g' inputfile`
|
||||
|
||||
|
||||
* 替换命令有两个参数:查找模式和替换字符串:`sed s/:/-----/ inputfile`
|
||||
* `s` 命令和它的参数是用任意一个字符来分隔的。这主要看你的习惯,在 99% 的时间中我都使用斜杠,但也会用其它的字符:`sed s%:%-----% inputfile`、`sed sX:X-----X inputfile` 或者甚至是 `sed 's : ----- ' inputfile`
|
||||
* 默认情况下,替换命令仅被应用到模式空间中匹配到的第一个字符串上。你可以通过在命令之后指定一个匹配指数作为标志来改变这种情况:`sed 's/:/-----/1' inputfile`、`sed 's/:/-----/2' inputfile`、`sed 's/:/-----/3' inputfile`、…
|
||||
* 如果你想执行一个全局替换(即:在模式空间上的每个非重叠匹配上进行),你需要增加 `g` 标志:`sed 's/:/-----/g' inputfile`
|
||||
* 在字符串替换中,出现的任何一个 `&` 符号都将被与查找模式匹配的子字符串替换:`sed 's/:/-&&&-/g' inputfile`、`sed 's/.../& /g' inputfile`
|
||||
* 圆括号(在扩展的正则表达式中的 `(...)` ,或者基本的正则表达式中的 `\(...\)`)被当做<ruby>捕获组<rt>capturing group</rt></ruby>。那是匹配字符串的一部分,可以在替换字符串中被引用。`\1` 是第一个捕获组的内容,`\2` 是第二个捕获组的内容,依次类推:`sed -E 's/(.)(.)/\2\1/g' inputfile`、`sed -E 's/(.):x:(.):(.*)/\1:\3/' inputfile`(后者之所能正常工作是因为 [正则表达式中的量词星号表示尽可能多的匹配,直到不匹配为止][21],并且它可以匹配许多个字符)
|
||||
* 在查找模式或替换字符串时,你可以通过使用一个反斜杠来去除任何字符的特殊意义:`sed 's/:/--\&--/g' inputfile`,`sed 's/\//\\/g' inputfile`
|
||||
|
||||
|
||||
所有的这些看起来有点抽象,下面是一些示例。首先,我想去显示我的测试输入文件的第一个字段并给它在右侧附加 20 个空格字符,我可以这样写:
|
||||
|
||||
```
|
||||
sed < inputfile -E -e '
|
||||
s/:/ / # 用 20 个空格替换第一个字段的分隔符
|
||||
s/(.{20}).*/\1/ # 只保留一行的前 20 个字符
|
||||
s/.*/| & |/ # 为了输出好看添加竖条
|
||||
s/:/ / # 用 20 个空格替换第一个字段的分隔符
|
||||
s/(.{20}).*/\1/ # 只保留一行的前 20 个字符
|
||||
s/.*/| & |/ # 为了输出好看添加竖条
|
||||
'
|
||||
|
||||
```
|
||||
|
||||
第二个示例是,如果我想将用户 sonia 的 UID/GID 修改为 1100,我可以这样写:
|
||||
|
||||
```
|
||||
sed -En -e '
|
||||
/sonia/{
|
||||
s/[0-9]+/1100/g
|
||||
p
|
||||
/sonia/{
|
||||
s/[0-9]+/1100/g
|
||||
p
|
||||
}' inputfile
|
||||
|
||||
```
|
||||
|
||||
注意在替换命令结束部分的 `g` 选项。这个选项改变了它的行为,因此它将查找全部的模式空间并替换,如果没有那个选项,它只替换查找到的第一个。
|
||||
|
||||
顺便说一下,这也是使用前面讲过的输出(`p`)命令的好机会,可以在命令运行时输出修改前后时刻模式空间的内容。因此,为了获得替换前后的内容,我可以这样写:
|
||||
顺便说一下,这也是使用前面讲过的输出(`p`)命令的好机会,可以在命令运行时输出修改前后的模式空间的内容。因此,为了获得替换前后的内容,我可以这样写:
|
||||
|
||||
```
|
||||
sed -En -e '
|
||||
/sonia/{
|
||||
p
|
||||
s/[0-9]+/1100/g
|
||||
p
|
||||
/sonia/{
|
||||
p
|
||||
s/[0-9]+/1100/g
|
||||
p
|
||||
}' inputfile
|
||||
|
||||
```
|
||||
|
||||
事实上,替换后输出一个行是很常见的用法,因此,替换命令也接受 `p` 选项:
|
||||
|
||||
```
|
||||
sed -En -e '/sonia/s/[0-9]+/1100/gp' inputfile
|
||||
|
||||
```
|
||||
|
||||
最后,我就不详细讲替换命令的 `w` 选项了,我们将在稍后的学习中详细介绍。
|
||||
|
||||
#### delete 命令
|
||||
### 删除命令
|
||||
|
||||
删除命令(`d`)用于清除模式空间的内容,然后立即开始下一个处理循环。这样它将会跳过隐式输出模式空间内容的行为,即便是你设置了自动输出标志(AP)也不会输出。
|
||||
|
||||
![The Sed `delete` command][22]
|
||||
|
||||
只输出一个文件前五行的一个很低效率的方法将是:
|
||||
|
||||
```
|
||||
sed -e '6,$d' inputfile
|
||||
|
||||
```
|
||||
|
||||
你猜猜看,我为什么说它很低效率?如果你猜不到,建议你再次去阅读前面的关于 quit 命令的章节,答案就在那里!
|
||||
你猜猜看,我为什么说它很低效率?如果你猜不到,建议你再次去阅读前面的关于退出命令的章节,答案就在那里!
|
||||
|
||||
当你组合使用正则表达式和地址,从输出中删除匹配的行时,删除命令将非常有用:
|
||||
|
||||
当你组合使用正则表达式和地址,从输出中删除匹配的行时,delete 命令将非常有用:
|
||||
```
|
||||
sed -e '/systemd/d' inputfile
|
||||
|
||||
```
|
||||
|
||||
#### next 命令
|
||||
### 次行命令
|
||||
|
||||
如果 Sed 命令不是在静默模式中运行,这个命令将输出当前模式空间的内容,然后,在任何情况下它将读取下一个输入行到模式空间中,并使用新的模式空间中的内容来运行当前循环中剩余的命令。
|
||||
如果 Sed 命令没有运行在静默模式中,这个命令(`n`)将输出当前模式空间的内容,然后,在任何情况下它将读取下一个输入行到模式空间中,并使用新的模式空间中的内容来运行当前循环中剩余的命令。
|
||||
|
||||
![The Sed `next` command][23]
|
||||
![The Sed next command][23]
|
||||
|
||||
用次行命令去跳过行的一个常见示例:
|
||||
|
||||
常见的用 next 命令去跳过行的一个示例:
|
||||
```
|
||||
cat -n inputfile | sed -n -e 'n;n;p'
|
||||
|
||||
```
|
||||
|
||||
在上面的例子中,Sed 将隐式地读取输入文件的第一行。但是 `next` 命令将丢弃对模式空间中的内容的输出(不输出是因为使用了 `-n` 选项),并从输入文件中读取下一行来替换模式空间中的内容。而第二个 `next` 命令做的事情和前一个是一模一样的,这就实现了跳过输入文件 2 行的目的。最后,这个脚本显式地输出包含在 `pattern ` 空间中的输入文件的第三行的内容。然后,Sed 将启动一个新的循环,由于 `next` 命令,它会隐式地读取第 4 行的内容,然后跳过它,同样地也跳过第 5 行,并输出第 6 行。如此循环,直到文件结束。总体来看,这个脚本就是读取输入文件然后每三行输出一行。
|
||||
在上面的例子中,Sed 将隐式地读取输入文件的第一行。但是次行命令将丢弃对模式空间中的内容的输出(不输出是因为使用了 `-n` 选项),并从输入文件中读取下一行来替换模式空间中的内容。而第二个次行命令做的事情和前一个是一模一样的,这就实现了跳过输入文件 2 行的目的。最后,这个脚本显式地输出包含在模式空间中的输入文件的第三行的内容。然后,Sed 将启动一个新的循环,由于次行命令,它会隐式地读取第 4 行的内容,然后跳过它,同样地也跳过第 5 行,并输出第 6 行。如此循环,直到文件结束。总体来看,这个脚本就是读取输入文件然后每三行输出一行。
|
||||
|
||||
使用次行命令,我们也可以找到一些显示输入文件的前五行的几种方法:
|
||||
|
||||
使用 next 命令,我们也可以找到一些显示输入文件的前五行的几种方法:
|
||||
```
|
||||
cat -n inputfile | sed -n -e '1{p;n;p;n;p;n;p;n;p}'
|
||||
cat -n inputfile | sed -n -e 'p;n;p;n;p;n;p;n;p;q'
|
||||
cat -n inputfile | sed -e 'n;n;n;n;q'
|
||||
|
||||
```
|
||||
|
||||
更有趣的是,如果你需要根据一些地址来处理行时,next 命令也非常有用:
|
||||
```
|
||||
cat -n inputfile | sed -n '/pulse/p' # 输出包含 "pulse" 的行
|
||||
cat -n inputfile | sed -n '/pulse/{n;p}' # 输出包含 "pulse" 之后的行
|
||||
cat -n inputfile | sed -n '/pulse/{n;n;p}' # 输出下面的行
|
||||
# 下一行
|
||||
# 包含 "pulse" 的行
|
||||
更有趣的是,如果你需要根据一些地址来处理行时,次行命令也非常有用:
|
||||
|
||||
```
|
||||
cat -n inputfile | sed -n '/pulse/p' # 输出包含 “pulse” 的行
|
||||
cat -n inputfile | sed -n '/pulse/{n;p}' # 输出包含 “pulse” 之后的行
|
||||
cat -n inputfile | sed -n '/pulse/{n;n;p}' # 输出包含 “pulse” 的行的下一行的下一行
|
||||
```
|
||||
|
||||
### 使用保持空间
|
||||
|
||||
到目前为止,我们所看到的命令都是仅使用了模式空间。但是,我们在文章的开始部分已经提到过,还有第二个缓冲区:保持空间,它完全由用户管理。它就是我们在第二节中描述的目标。
|
||||
|
||||
#### exchange 命令
|
||||
#### 交换命令
|
||||
|
||||
正如它的名字所表示的,exchange 命令(`x`)将交换保持空间和模式空间的内容。记住,你只要没有把任何东西放入到保持空间中,那么保持空间就是空的。
|
||||
正如它的名字所表示的,交换命令(`x`)将交换保持空间和模式空间的内容。记住,你只要没有把任何东西放入到保持空间中,那么保持空间就是空的。
|
||||
|
||||
![The Sed `exchange` command][24]
|
||||
![The Sed exchange command][24]
|
||||
|
||||
作为第一个示例,我们可使用交换命令去反序输出一个输入文件的前两行:
|
||||
|
||||
作为第一个示例,我们可使用 exchange 命令去反序输出一个输入文件的前两行:
|
||||
```
|
||||
cat -n inputfile | sed -n -e 'x;n;p;x;p;q'
|
||||
|
||||
```
|
||||
|
||||
当然,在你设置 `hold` 之后你并没有立即使用它的内容,因为只要你没有显式地去修改它,保持空间中的内容就保持不变。在下面的例子中,我在输入一个文件的前五行后,使用它去删除第一行:
|
||||
当然,在你设置保持空间之后你并没有立即使用它的内容,因为只要你没有显式地去修改它,保持空间中的内容就保持不变。在下面的例子中,我在输入一个文件的前五行后,使用它去删除第一行:
|
||||
|
||||
```
|
||||
cat -n inputfile | sed -n -e '
|
||||
1{x;n} # 交换 hold 和 pattern 空间
|
||||
# 保存第 1 行到 hold 空间中
|
||||
# 然后读取第 2 行
|
||||
1{x;n} # 交换保持和模式空间
|
||||
# 保存第 1 行到保持空间中
|
||||
# 然后读取第 2 行
|
||||
5{
|
||||
p # 输出第 5 行
|
||||
x # 交换 hold 和 pattern 空间
|
||||
# 去取得第 1 行的内容放回到
|
||||
# pattern 空间
|
||||
p # 输出第 5 行
|
||||
x # 交换保持和模式空间
|
||||
# 去取得第 1 行的内容放回到模式空间
|
||||
}
|
||||
|
||||
1,5p # 输出第 2 到第 5 行
|
||||
# (不要输错了!尝试找出这个规则
|
||||
# 没有在第 1 行上运行的原因;)
|
||||
1,5p # 输出第 2 到第 5 行
|
||||
# (并没有输错!尝试找出这个规则
|
||||
# 没有在第 1 行上运行的原因 ;)
|
||||
'
|
||||
|
||||
```
|
||||
|
||||
#### hold 命令
|
||||
#### 保持命令
|
||||
|
||||
hold 命令(`h`)是用于将模式空间中的内容保存到保持空间中。但是,与 exchange 命令不同的是,模式空间中的内容不会被改变。hold 命令有两种用法:
|
||||
保持命令(`h`)是用于将模式空间中的内容保存到保持空间中。但是,与交换命令不同的是,模式空间中的内容不会被改变。保持命令有两种用法:
|
||||
|
||||
* `h`
|
||||
将复制模式空间中的内容到保持空间中,将覆盖保持空间中任何已经存在的内容。
|
||||
* `h` 将复制模式空间中的内容到保持空间中,覆盖保持空间中任何已经存在的内容。
|
||||
* `H` 将模式空间中的内容追加到保持空间中,使用一个新行作为分隔符。
|
||||
|
||||
* `H`
|
||||
使用一个独立的新行,追加模式空间中的内容到保持空间中。
|
||||
![The Sed hold command][25]
|
||||
|
||||
上面使用交换命令的例子可以使用保持命令重写如下:
|
||||
|
||||
|
||||
|
||||
![The Sed `hold` command][25]
|
||||
|
||||
上面使用 exchange 命令的例子可以使用 hold 命令重写如下:
|
||||
```
|
||||
cat -n inputfile | sed -n -e '
|
||||
1{h;n} # 保存第 1 行的内容到 hold 缓冲区并继续
|
||||
5{ # 到第 5 行
|
||||
x # 交换 pattern 和 hold 空间
|
||||
# (现在 pattern 空间包含了第 1 行)
|
||||
H # 在 hold 空间的第 5 行后追回第 1 行
|
||||
x # 再次交换取回第 5 行并将第 1 行插入
|
||||
# 到 pattern 空间
|
||||
1{h;n} # 保存第 1 行的内容到保持缓冲区并继续
|
||||
5{ # 在第 5 行
|
||||
x # 交换模式和保持空间
|
||||
# (现在模式空间包含了第 1 行)
|
||||
H # 在保持空间的第 5 行后追加第 1 行
|
||||
x # 再次交换第 5 行和第 1 行,第 5 行回到模式空间
|
||||
}
|
||||
|
||||
1,5p # 输出第 2 行到第 5 行
|
||||
# (不要输错!尝试去打到为什么这个规则
|
||||
# 不在第 1 行上运行;)
|
||||
1,5p # 输出第 2 行到第 5 行
|
||||
# (没有输错!尝试去找到为什么这个规则
|
||||
# 不在第 1 行上运行 ;)
|
||||
'
|
||||
|
||||
```
|
||||
|
||||
#### get 命令
|
||||
#### 获取命令
|
||||
|
||||
get 命令(`g`)与 hold 命令恰好相反:它从保持空间中取得内容并将它置入到模式空间中。同样它也有两种方式:
|
||||
获取命令(`g`)与保持命令恰好相反:它从保持空间中取得内容并将它置入到模式空间中。同样它也有两种方式:
|
||||
|
||||
* `g`
|
||||
它将复制保持空间中的内容并将其放入到模式空间,覆盖 `pattern`空间中已存在的任何内容
|
||||
* `g` 将复制保持空间中的内容并将其放入到模式空间,覆盖模式空间中已存在的任何内容
|
||||
* `G` 将保持空间中的内容追加到模式空间中,并使用一个新行作为分隔符
|
||||
|
||||
* `G`
|
||||
使用一个单独的新行,追加保持空间中的内容到模式空间中
|
||||
![The Sed get command][26]
|
||||
|
||||
将保持命令和获取命令一起使用,可以允许你去存储并调回数据。作为一个小挑战,我让你重写前一节中的示例,将输入文件的第 1 行放置在第 5 行之后,但是这次必须使用获取和保持命令(使用大写或小写命令的版本)而不能使用交换命令。带点小运气,可以更简单!
|
||||
|
||||
同时,我可以给你展示另一个示例,它能给你一些灵感。目标是将拥有登录 shell 权限的用户与其它用户分开:
|
||||
|
||||
|
||||
![The Sed `get` command][26]
|
||||
|
||||
将 hold 命令和 get 命令一起使用,可以允许你去存储并调回数据。作为一个小挑战,我让你重写前一节中的示例,将输入文件的第 1 行放置在第 5 行之后,但是这次必须使用 get 和 hold 命令(注意大小写)而不能使用 exchange 命令。只要运气好,它将使那个方式更简单!
|
||||
|
||||
在这期间,我可以给你展示另一个示例,它能给你一些灵感。目标是将拥有登录 shell 权限的用户与其它用户分开:
|
||||
```
|
||||
cat -n inputfile | sed -En -e '
|
||||
\=(/usr/sbin/nologin|/bin/false)$= { H;d; }
|
||||
# 追回匹配的行到 hold 空间
|
||||
# 然后继续下一个循环
|
||||
p # 输出其它行
|
||||
$ { g;p } # 在最后一行上
|
||||
# 取得并输出 hold 空间中的内容
|
||||
# 追回匹配的行到保持空间
|
||||
# 然后继续下一个循环
|
||||
p # 输出其它行
|
||||
$ { g;p } # 在最后一行上
|
||||
# 获取并打印保持空间中的内容
|
||||
'
|
||||
|
||||
```
|
||||
|
||||
### 复习 print、delete 和 next
|
||||
|
||||
现在你已经更熟悉使用 hold 空间了,我们回到 print、delete 和 next 命令。我们已经讨论了小写的 `p`、`d` 和 `n` 命令了。而它们也有大写的版本。因为每个命令都有大小写版本,似乎是 Sed 的习惯,这些命令的大写版本将与多行缓冲区有关:
|
||||
|
||||
* `P`
|
||||
将模式空间中第一个新行之前的内容输出
|
||||
|
||||
* `D`
|
||||
删除模式空间中的内容并且包含新行,然后不读取任何新的输入而是使用剩余的文本去重启一个循环
|
||||
|
||||
* `N`
|
||||
使用一个换行符作为新旧数据的分隔符,然后读取并追加一个输入的新行到模式空间。继续运行当前的循环。
|
||||
|
||||
### 复习打印、删除和次行命令
|
||||
|
||||
现在你已经更熟悉使用保持空间了,我们回到打印、删除和次行命令。我们已经讨论了小写的 `p`、`d` 和 `n` 命令了。而它们也有大写的版本。因为每个命令都有大小写版本,似乎是 Sed 的习惯,这些命令的大写版本将与多行缓冲区有关:
|
||||
|
||||
* `P` 将模式空间中第一个新行之前的内容输出
|
||||
* `D` 删除模式空间中第一个新行之前的内容(包含新行),然后不读取任何新的输入而是使用剩余的文本去重启一个循环
|
||||
* `N` 读取输入并追加一个新行到模式空间,用一个新行作为新旧数据的分隔符。继续运行当前的循环。
|
||||
|
||||
![The Sed uppercase `Delete` command][27]
|
||||
|
||||
![The Sed uppercase `Next` command][28]
|
||||
|
||||
这些命令的使用场景主要用于实现队列([FIFO 列表][29])。从一个输入文件中删除最后 5 行就是一个很权威的例子:
|
||||
|
||||
```
|
||||
cat -n inputfile | sed -En -e '
|
||||
1 { N;N;N;N } # 确保 pattern 空间中包含 5 行
|
||||
1 { N;N;N;N } # 确保模式空间中包含 5 行
|
||||
|
||||
N # 追加第 6 行到队列中
|
||||
P # 输出队列的第 1 行
|
||||
D # 删除队列的第 1 行
|
||||
N # 追加第 6 行到队列中
|
||||
P # 输出队列的第 1 行
|
||||
D # 删除队列的第 1 行
|
||||
'
|
||||
|
||||
```
|
||||
|
||||
作为第二个示例,我们可以在两个列上显示输入数据:
|
||||
|
||||
```
|
||||
# 输出两列
|
||||
sed < inputfile -En -e '
|
||||
$!N # 追加一个新行到 pattern 空间
|
||||
# 除了输入文件的最后一行
|
||||
# 当在输入文件的最后一行使用 N 命令时
|
||||
# GNU Sed 和 POSIX Sed 的行为是有差异的
|
||||
# 需要使用一个技巧去处理这种情况
|
||||
# https://www.gnu.org/software/sed/manual/sed.html#N_005fcommand_005flast_005fline
|
||||
$!N # 追加一个新行到模式空间
|
||||
# 除了输入文件的最后一行
|
||||
# 当在输入文件的最后一行使用 N 命令时
|
||||
# GNU Sed 和 POSIX Sed 的行为是有差异的
|
||||
# 需要使用一个技巧去处理这种情况
|
||||
# https://www.gnu.org/software/sed/manual/sed.html#N_005fcommand_005flast_005fline
|
||||
|
||||
# 用空间填充第 1 行的第 1 个字段
|
||||
# 并丢弃其余行
|
||||
s/:.*\n/ \n/
|
||||
s/:.*// # 除了第 2 行上的第 1 个字段外,丢弃其余的行
|
||||
s/(.{20}).*\n/\1/ # 修剪并连接行
|
||||
p # 输出结果
|
||||
# 用空间填充第 1 行的第 1 个字段
|
||||
# 并丢弃其余行
|
||||
s/:.*\n/ \n/
|
||||
s/:.*// # 除了第 2 行上的第 1 个字段外,丢弃其余的行
|
||||
s/(.{20}).*\n/\1/ # 修剪并连接行
|
||||
p # 输出结果
|
||||
'
|
||||
|
||||
```
|
||||
|
||||
### 分支
|
||||
|
Loading…
Reference in New Issue
Block a user