Bash: 如何对某些行进行排除,但排除中间的某些行?
Bash: how to certain lines but exclude certain lines in between?
我有一个如下所示的文件:
a: 0
a: 0
a: 0
a: 1
b: 1
c: 1
d: 1
e: 1
f: 1
a: 2
b: 2
c: 2
d: 2
e: 2
f: 2
a: 3
b: 3
c: 3
d: 3
e: 3
f: 3
c: 4
c: 4
c: 4
我想捕获并输出 <a line><anything other than an a or c line><c line>
形式的所有 a
和 c
行,因此输出看起来像:
a: 1
c: 1
a: 2
c: 2
a: 3
c: 3
请注意,开头的 a: 0
行和结尾的 c: 4
行都没有被捕获,因为它们不遵循我提到的模式。另请注意,a
和 c
行之间的 b
行已被删除。
我一直在尝试使用 Bash 的 pcregrep 进行环视,但还没有找到解决方案。有什么想法吗?
谢谢!
使用 awk
尝试:
$ awk -F: '=="a"{aline=[=10=]} =="c"{if(aline)print aline ORS [=10=] ORS; aline=""}' file
a: 1
c: 1
a: 2
c: 2
a: 3
c: 3
工作原理
默认情况下,awk 一次读取一行。
-F:
这告诉 awk 使用 :
作为字段分隔符。
=="a"{aline=[=15=]}
每次观察到 a
行时,将该行保存在变量 aline
中。
=="c"{if(aline)print aline ORS [=18=] ORS; aline=""}
每次观察到 c
行时,检查我们是否有非空行 aline
。如果是,则打印 aline
和当前行,以换行符分隔。此外,将 aline
设置回空字符串。
多行版本
对于那些喜欢将命令分散在多行中的人:
awk -F: '
=="a"{
aline=[=11=]
}
=="c"{
if(aline)
print aline ORS [=11=] ORS
aline=""
}' file
使用 sed
$ sed -n '/^a/h; /^c/{x;/^a/{p;x;s/$/\n/;p};h}' file
a: 1
c: 1
a: 2
c: 2
a: 3
c: 3
工作原理
-n
这告诉 sed 不要打印任何东西,除非我们明确要求它。
/^a/h
任何时候我们有以 a
开头的行,我们将其保存到保留 space.
/^c/{ x; /^a/{ p; x; s/$/\n/; p}; h}
每当我们有一行以 c
开头时,我们:
我们交换 (x
) 模式 space 与保留 space.
如果新模式space以a
开头,那么我们打印(p
)它,然后再次交换(x
),在新模式 space (s/$/\n/
) 的末尾添加一个新行并打印 (p
) 它。
最后我们将当前模式space(以c
开头)保存到space.
我有一个如下所示的文件:
a: 0
a: 0
a: 0
a: 1
b: 1
c: 1
d: 1
e: 1
f: 1
a: 2
b: 2
c: 2
d: 2
e: 2
f: 2
a: 3
b: 3
c: 3
d: 3
e: 3
f: 3
c: 4
c: 4
c: 4
我想捕获并输出 <a line><anything other than an a or c line><c line>
形式的所有 a
和 c
行,因此输出看起来像:
a: 1
c: 1
a: 2
c: 2
a: 3
c: 3
请注意,开头的 a: 0
行和结尾的 c: 4
行都没有被捕获,因为它们不遵循我提到的模式。另请注意,a
和 c
行之间的 b
行已被删除。
我一直在尝试使用 Bash 的 pcregrep 进行环视,但还没有找到解决方案。有什么想法吗?
谢谢!
使用 awk
尝试:
$ awk -F: '=="a"{aline=[=10=]} =="c"{if(aline)print aline ORS [=10=] ORS; aline=""}' file
a: 1
c: 1
a: 2
c: 2
a: 3
c: 3
工作原理
默认情况下,awk 一次读取一行。
-F:
这告诉 awk 使用
:
作为字段分隔符。=="a"{aline=[=15=]}
每次观察到
a
行时,将该行保存在变量aline
中。=="c"{if(aline)print aline ORS [=18=] ORS; aline=""}
每次观察到
c
行时,检查我们是否有非空行aline
。如果是,则打印aline
和当前行,以换行符分隔。此外,将aline
设置回空字符串。
多行版本
对于那些喜欢将命令分散在多行中的人:
awk -F: '
=="a"{
aline=[=11=]
}
=="c"{
if(aline)
print aline ORS [=11=] ORS
aline=""
}' file
使用 sed
$ sed -n '/^a/h; /^c/{x;/^a/{p;x;s/$/\n/;p};h}' file
a: 1
c: 1
a: 2
c: 2
a: 3
c: 3
工作原理
-n
这告诉 sed 不要打印任何东西,除非我们明确要求它。
/^a/h
任何时候我们有以
a
开头的行,我们将其保存到保留 space./^c/{ x; /^a/{ p; x; s/$/\n/; p}; h}
每当我们有一行以
c
开头时,我们:我们交换 (
x
) 模式 space 与保留 space.如果新模式space以
a
开头,那么我们打印(p
)它,然后再次交换(x
),在新模式 space (s/$/\n/
) 的末尾添加一个新行并打印 (p
) 它。最后我们将当前模式space(以
c
开头)保存到space.