使用sed在模式匹配后打印上一行?

ayr*_*nna 12 sed

每次找到匹配项时,我都想打印上一行。我知道grep -A-B选项。但是我的 Solaris 5.10 机器不支持这些选项。

我想要只使用sed.

Foo.txt

Name is : sara
age is : 10
Name is : john
age is : 20
Name is : Ron
age is : 10
Name is : peggy
age is : 30
Run Code Online (Sandbox Code Playgroud)

Out.txt

Name is : sara
Name is : Ron
Run Code Online (Sandbox Code Playgroud)

我试图匹配的模式是age is : 10.

我的环境,Solaris 5.10。

Joh*_*024 24

$ sed -n '/age is : 10/{x;p;d;}; x' Foo.txt 
Name is : sara
Name is : Ron
Run Code Online (Sandbox Code Playgroud)

以上是在 GNU sed 上测试的。如果 Solaris 的 sed 不支持使用分号链接命令,请尝试:

$ sed -n -e '/age is : 10/{x;p;d;}' -e x Foo.txt 
Name is : sara
Name is : Ron
Run Code Online (Sandbox Code Playgroud)

这个怎么运作

sed 有一个保持空间和一个模式空间。换行符被读入模式空间。这个脚本的想法是将前一行保存在保持空间中。

  • /age is : 10/{x;p;d;}

    如果当前行包含age is : 10,则执行:

    x : 交换模式并保留空间,以便前一行在模式空间中

    p : 打印前一行

    d : 删除模式空间并开始处理下一行

  • x

    这仅在不包含age is : 10. 在这种情况下,它将当前行保存在保持空间中。

反其道而行之

假设我们要打印年龄不是10岁的人的姓名:

$ sed -n -e '/age is : 10/{x;d}' -e '/age is :/{x;p;d;}' -e x Foo.txt 
Name is : john
Name is : peggy
Run Code Online (Sandbox Code Playgroud)

上面的命令在开头添加了一个命令/age is : 10/{x;d},以忽略任何 10 岁以下的人。后面的命令/age is :/{x;p;d;}现在接受所有剩余的年龄。


cuo*_*glm 5

POSIXly:

$ sed -n '/age is : 10/{g
1!p
}
h
' file
Run Code Online (Sandbox Code Playgroud)

如果当前行不匹配,则打印上一行age is : 10

$ sed -n '
$!N
/age is : 10/d
P
' file
Run Code Online (Sandbox Code Playgroud)