使用sed删除两个匹配模式之间的所有行,包括匹配的行

时间:2019-09-08 19:21:06

标签: shell awk sed data-manipulation

我需要删除文件中匹配的特定模式和匹配的行之间的行。

在下面的代码中,我想从对象主机“ kali” {删除行到下次出现的} (而不是最后一次出现的})中的行。并在删除后删除空白。

object Host "linux" {
import "windows"
address = "linux"
groups = ["linux"]
}


object Host "kali" {
import "linux"
address = "linux"
groups = [linux ]
}


object Host "windows" {
import "linux"
address = "linux"
groups = ["windows" ]
}
  
    

这是我的代码

  
clear
echo -e  "Enter the host to delete in config file"
cat > deletionfile.txt
clear
while read host
do
loc=`grep -il 'object.*Host.*"$host"' /home/afrith/config-file/*.conf`
sed -i "/^object.*Host.*\"$host\".*{$/,/^}$/d" $loc
done < deletionfile.txt
rm -rf deletionfile.txt

执行脚本时出现错误提示:

sed:没有输入文件

  

这是预期的输出:(当我将kali作为脚本的输入时。)

object Host "linux" {
import "windows"
address = "linux"
groups = ["linux"]
}


object Host "windows" {
import "linux"
address = "linux"
groups = ["windows" ]
}

5 个答案:

答案 0 :(得分:6)

以下sed应该删除object Host "kali" {}之间的所有行。

sed '/^object Host "kali" {$/,/^}$/d'

答案 1 :(得分:4)

尝试一下:

sed -i -Ez 's/object Host \"kali\"\s*\{[^}]*\}//g' your_file

或者,您可以尝试以下操作(也会删除空行):

sed  '/object Host "kali"\s*{$/,/[^}]*}/d; /^$/d' your_file

输出将是:

object Host "linux" {
import "windows"
address = "linux"
groups = ["linux"]
}
object Host "windows" {
import "linux"
address = "linux"
groups = ["windows" ]
}

答案 2 :(得分:1)

其中一种方法是使用AWK。您需要将记录分隔符更改为}并运行此awk '!/kali/;BEGIN{RS="}"; ORS="}"}' < your_file,输出就是您想要的。

我已将问题中给出的文本保存在文件test.txt

ajay@DESKTOP-PCMKVK6:~$ cat test.txt
object Host "linux" {
import "windows"
address = "linux"
groups = ["linux"]
}


object Host "kali" {
import "linux"
address = "linux"
groups = [linux ]
}


object Host "windows" {
import "linux"
address = "linux"
groups = ["windows" ]
}

现在我们需要运行此awk命令awk '!/kali/;BEGIN{RS="}"; ORS="}"}' < test.txt

ajay@DESKTOP-PCMKVK6:~$ awk '!/kali/;BEGIN{RS="}"; ORS="}"}' < test.txt
object Host "linux" {
import "windows"
address = "linux"
groups = ["linux"]
}


object Host "windows" {
import "linux"
address = "linux"
groups = ["windows" ]
}
}ajay@DESKTOP-PCMKVK6:~$ 

此外,您可以使用其他答案中提到的sed,也可以添加-i选项以在同一文件中进行更改 sed -i '/^object Host "kali" {$/,/^}$/d' file_name

答案 3 :(得分:1)

通过将记录选择器设置为空,可以使gnu awk处于块模式。

awk -v RS= -v ORS="\n\n" '/object Host "kali"/ {next} 1' file
object Host "linux" {
import "windows"
address = "linux"
groups = ["linux"]
}

object Host "windows" {
import "linux"
address = "linux"
groups = ["windows" ]
}
  • /object Host "kali"/ {next}如果块包含object Host "kali",请跳过
  • 1始终为true,执行默认操作,打印

答案 4 :(得分:1)

这可能对您有用(GNU sed):

sed -n '/^object Host "kali" {/{:a;n;/^}/d;ba};p' file

或者:

sed '/^object Host "kali" {/{:a;N;/^}/Md;ba}' file

第一个解决方案的行为类似于grep,并选择不打印以object Host "kali" {开头和以}开头的行。

第二种解决方案是收集以上两种模式之间的线,然后删除这些线。

如果第一个模式匹配,第一个解决方案将更改文件,而第二个解决方案仅在两个模式都匹配时更改文件。这是因为如果要求命令nN读取文件末尾之外的内容,它们将导致sed结束处理。如果设置了n选项,-n将安静地结束,而N将在终止之前打印出模式空间中的所有内容。

/^}/在行首匹配},在第二种解决方案中,添加了M标志,该标志打开多行匹配,即^$在换行符之后/之前匹配,此标志特定于GNU sed。 /\n}/将具有相同的效果。如果匹配更加轻松,即匹配任何出现的},则/}/就足够了。