如何grep一块文字?

时间:2014-12-10 16:55:45

标签: bash grep

我想从此文件中删除特定服务器的块

NameVirtualHost *
<VirtualHost *>
DocumentRoot "/Applications/MAMP/htdocs"
ServerName localhost
</VirtualHost>
<VirtualHost *>
DocumentRoot "/Applications/MAMP/htdocs/bedrock/web"
ServerName bedrock
</VirtualHost>
<VirtualHost *>
DocumentRoot "documentroot"
ServerName newserver
</VirtualHost>

到目前为止,我已经使用了以下内容,但它似乎没有给我正确的结果,而是为每个块(内部grep)的每一行单独greps。

grep -vF "$(grep -w -B 2 -A 1 'newserver'/Applications/MAMP/conf/apache/httpd.conf)" /Applications/MAMP/conf/apache/httpd.conf;

以上结果如下:

NameVirtualHost *
DocumentRoot "/Applications/MAMP/htdocs"
ServerName localhost
DocumentRoot "/Applications/MAMP/htdocs/bedrock/web"
ServerName bedrock

而我想要以下内容:

NameVirtualHost *
<VirtualHost *>
DocumentRoot "/Applications/MAMP/htdocs"
ServerName localhost
</VirtualHost>
<VirtualHost *>
DocumentRoot "/Applications/MAMP/htdocs/bedrock/web"
ServerName bedrock
</VirtualHost>

4 个答案:

答案 0 :(得分:2)

单凭awk:

$ awk '!/ServerName newserver/{printf "%s%s", $0, RS}' RS='</VirtualHost>' file

NameVirtualHost *
<VirtualHost *>
DocumentRoot "/Applications/MAMP/htdocs"
ServerName localhost
</VirtualHost>
<VirtualHost *>
DocumentRoot "/Applications/MAMP/htdocs/bedrock/web"
ServerName bedrock
</VirtualHost>

RS</VirtualHost>定义为记录分隔符,awk将打印与其中$0不匹配的记录(ServerName newserver)。然后再次打印RS</VirtualHost>),当我们将RS更改为时,会删除该{{1}}。

答案 1 :(得分:2)

另一个diff和初始命令的一部分:

diff  <(grep -w -B 2 -A 1 'newserver' /Applications/MAMP/conf/apache/httpd.conf) \
      /Applications/MAMP/conf/apache/httpd.conf  | 
grep -e '^> ' | sed -e 's/^> //'

答案 2 :(得分:1)

$ tac vhost | awk 'NR>4' | tac
NameVirtualHost *
<VirtualHost *>
DocumentRoot "/Applications/MAMP/htdocs"
ServerName localhost
</VirtualHost>
<VirtualHost *>
DocumentRoot "/Applications/MAMP/htdocs/bedrock/web"
ServerName bedrock
</VirtualHost>

这是一个&#39;技巧&#39;按其包含的已知行数删除最后一个Vhost

答案 3 :(得分:1)

如果您要删除带有 ServerName newserver 的条目,请使用此perl one-liner:

perl -0pe 's~(?s)\s?<VirtualHost[^>]*>((?!</VirtualHost>).)*ServerName newserver.*</VirtualHost>~~' file
NameVirtualHost *
<VirtualHost *>
DocumentRoot "/Applications/MAMP/htdocs"
ServerName localhost
</VirtualHost>
<VirtualHost *>
DocumentRoot "/Applications/MAMP/htdocs/bedrock/web"
ServerName bedrock
</VirtualHost>

使用变量:

s='newserver'
perl -0pe 's~(?s)\s?<VirtualHost[^>]*>((?!</VirtualHost>).)*ServerName '"$s"'.*</VirtualHost>~~' file

RegEx Demo

说明:

此perl命令使用与从这两个标记开始的块匹配的正则表达式:

<VirtualHost[^>]*>

</VirtualHost>

并在这两种模式之间找到这种模式:

ServerName newserver

它使用(?!</VirtualHost>)使用负前瞻模式,只有当ServerName测试结束时才会确定只找到匹配。