sed - 删除匹配模式前后的 n 行
sed - deleting n lines preceeding and following the matching pattern
删除匹配模式后的 "n" 行很容易,使用类似的东西:
IFM_MOUNT="/opt/insiteone/fuse-mount2/ifm"
sed -i "\|$IFM_MOUNT|,+6 d" smb.conf (deletes lines matching and next 6 lines)
但我的问题是,我也想删除匹配模式之前的 2 行。
如何实现?
我将调用该命令的文件是一个 Samba 配置文件,如下所示:
[DCCAArchive1]
comment = DCCA Archive File System
path = /opt/insiteone/fuse-mount1/ifm
read only = No
public = yes
case sensitive = yes
writable = yes
create mask=0777
guest ok = Yes
[DCCAArchive2]
comment = DCCA Archive File System
path = /opt/insiteone/fuse-mount2/ifm
read only = No
public = yes
case sensitive = yes
writable = yes
create mask=0777
guest ok = Yes
[DCCAArchive3]
comment = DCCA Archive File System
path = /opt/insiteone/fuse-mount3/ifm
read only = No
public = yes
case sensitive = yes
writable = yes
create mask=0777
guest ok = Yes
您使用以下 sed
命令:
sed -r ':a;N;s~([^\n]*\n){2}[^\n]*'"$search"'\n~~;ba' file
该命令基本上是一个循环。 :a
在循环开始处标记一个标签。 N
读取下一行输入并将其附加到模式缓冲区。 s~([^\n]+\n){2}PATTERN\n~~
将删除模式和它之前的两行。请注意,我使用 ~
作为分隔符,因为输入数据包含 "standard" 分隔符 /
。 ba
将分支回到循环的开始。在输入结束时,修改后的文件被打印 $p
.
顺便说一句,只需将搜索模式中的 2
更改为您想要的任何内容,即可将模式更改为任意数量的前几行。
正如我评论的那样,如果格式是固定的(数据块之间的空行),这一行就可以完成工作:
awk -v RS="" '!/PATTERN/' input
如果不是这种情况,你可以试试这个 awk 单行代码:
awk '{a[NR]=[=11=]}/PATTERN/{for(i=NR-2;i<=NR+6;i++)d[i]=1}
END{for(i=1;i<=NR;i++)if(!d[i])print a[i]}' input
一个测试
- 与
ifm
简化 PATTERN
- "data blocks"
之间没有空行
遵循您的规则:删除行 hit-2 -> hit+6
kent$ cat f
fooooooooo
[DCCAArchive1]
comment = DCCA Archive File System
path = /opt/insiteone/fuse-mount1/ifm
read only = No
public = yes
case sensitive = yes
writable = yes
create mask=0777
guest ok = Yes
barrrrrrrrrrrr
[DCCAArchive2]
comment = DCCA Archive File System
path = /opt/insiteone/fuse-mount2/ifm
read only = No
public = yes
case sensitive = yes
writable = yes
create mask=0777
guest ok = Yes
kent$ awk '{a[NR]=[=12=]}/ifm/{for(i=NR-2;i<=NR+6;i++)d[i]=1}END{for(i=1;i<=NR;i++)if(!d[i])print a[i]} ' f
fooooooooo
barrrrrrrrrrrr
编辑
使用来自 shell 变量的模式:
kent$ PAT="/fuse-mount2/ifm"
kent$ awk -v p="$PAT" '{a[NR]=[=13=]}{if(match([=13=],p)>0){for(i=NR-2;i<=NR+6;i++)d[i]=1}}END{for(i=1;i<=NR;i++)if(!d[i])print a[i]} ' f
fooooooooo
[DCCAArchive1]
comment = DCCA Archive File System
path = /opt/insiteone/fuse-mount1/ifm
read only = No
public = yes
case sensitive = yes
writable = yes
create mask=0777
guest ok = Yes
barrrrrrrrrrrr
删除匹配模式后的 "n" 行很容易,使用类似的东西:
IFM_MOUNT="/opt/insiteone/fuse-mount2/ifm"
sed -i "\|$IFM_MOUNT|,+6 d" smb.conf (deletes lines matching and next 6 lines)
但我的问题是,我也想删除匹配模式之前的 2 行。
如何实现? 我将调用该命令的文件是一个 Samba 配置文件,如下所示:
[DCCAArchive1]
comment = DCCA Archive File System
path = /opt/insiteone/fuse-mount1/ifm
read only = No
public = yes
case sensitive = yes
writable = yes
create mask=0777
guest ok = Yes
[DCCAArchive2]
comment = DCCA Archive File System
path = /opt/insiteone/fuse-mount2/ifm
read only = No
public = yes
case sensitive = yes
writable = yes
create mask=0777
guest ok = Yes
[DCCAArchive3]
comment = DCCA Archive File System
path = /opt/insiteone/fuse-mount3/ifm
read only = No
public = yes
case sensitive = yes
writable = yes
create mask=0777
guest ok = Yes
您使用以下 sed
命令:
sed -r ':a;N;s~([^\n]*\n){2}[^\n]*'"$search"'\n~~;ba' file
该命令基本上是一个循环。 :a
在循环开始处标记一个标签。 N
读取下一行输入并将其附加到模式缓冲区。 s~([^\n]+\n){2}PATTERN\n~~
将删除模式和它之前的两行。请注意,我使用 ~
作为分隔符,因为输入数据包含 "standard" 分隔符 /
。 ba
将分支回到循环的开始。在输入结束时,修改后的文件被打印 $p
.
顺便说一句,只需将搜索模式中的 2
更改为您想要的任何内容,即可将模式更改为任意数量的前几行。
正如我评论的那样,如果格式是固定的(数据块之间的空行),这一行就可以完成工作:
awk -v RS="" '!/PATTERN/' input
如果不是这种情况,你可以试试这个 awk 单行代码:
awk '{a[NR]=[=11=]}/PATTERN/{for(i=NR-2;i<=NR+6;i++)d[i]=1}
END{for(i=1;i<=NR;i++)if(!d[i])print a[i]}' input
一个测试
- 与
ifm
简化PATTERN
- "data blocks" 之间没有空行
遵循您的规则:删除行
hit-2 -> hit+6
kent$ cat f fooooooooo [DCCAArchive1] comment = DCCA Archive File System path = /opt/insiteone/fuse-mount1/ifm read only = No public = yes case sensitive = yes writable = yes create mask=0777 guest ok = Yes barrrrrrrrrrrr [DCCAArchive2] comment = DCCA Archive File System path = /opt/insiteone/fuse-mount2/ifm read only = No public = yes case sensitive = yes writable = yes create mask=0777 guest ok = Yes kent$ awk '{a[NR]=[=12=]}/ifm/{for(i=NR-2;i<=NR+6;i++)d[i]=1}END{for(i=1;i<=NR;i++)if(!d[i])print a[i]} ' f fooooooooo barrrrrrrrrrrr
编辑
使用来自 shell 变量的模式:
kent$ PAT="/fuse-mount2/ifm"
kent$ awk -v p="$PAT" '{a[NR]=[=13=]}{if(match([=13=],p)>0){for(i=NR-2;i<=NR+6;i++)d[i]=1}}END{for(i=1;i<=NR;i++)if(!d[i])print a[i]} ' f
fooooooooo
[DCCAArchive1]
comment = DCCA Archive File System
path = /opt/insiteone/fuse-mount1/ifm
read only = No
public = yes
case sensitive = yes
writable = yes
create mask=0777
guest ok = Yes
barrrrrrrrrrrr