我有如下配置文件:
define host{
host_name xxxxxxxx1748
use windows-server
alias Comet
hostgroups +bu-automotiveprd,screen-automotiveprd2
address XXX.XXX.XXX.XXX
}
define host{
host_name yyyyyyyyy991
use aix-server
alias
hostgroups +bu-automotiveprd,screen-automotiveprd2
address YYY.YYY.YYY.YYY
}
我想搜索主机名,如果匹配,输出应如下所示:
示例 - 假设我想搜索yyyyyyyyy991
主机。
那么输出必须如下所示:
define host{
host_name yyyyyyyyy991
use aix-server
alias
hostgroups +bu-automotiveprd,screen-automotiveprd2
address YYY.YYY.YYY.YYY
}
答案1
尝试这个,
perl -0777 -ne '/([^\n]*{[^}]*(yyyyyyyyy991)[^}]*})/ && print "$1\n"' file
解释:
perl -0777
运行 perl 并将整个文件作为一行读取。-ne
对于每一行 (n
),执行e
以下 ( ) 操作。/(pattern)/ && print "$1\n"
匹配正则表达式模式并将其添加为第一个匹配组 ($1
),然后打印它。
模式:
[^\n]*{ ... }
匹配从行首开始的任何内容,包括“{”到下一个“}”- 与
...
存在[^}]*(yyyyyyyyy991)[^}]*
:- 匹配任何不是的字符
}
- 必须包括
yyyyyyyyy991
某处。
- 匹配任何不是的字符
答案2
如果您grep
支持它,您可以使用该-z
选项使其吞噬整个文件:
$ grep -ozE 'define[^}]*host_name yyyyyyyyy991.+?}.' file
define host{
host_name yyyyyyyyy991
use aix-server
alias
hostgroups +bu-automotiveprd,screen-automotiveprd2
address YYY.YYY.YYY.YYY
}
使用的选项grep
是(来自man
GNU 页面grep
):
-z, --null-data
Treat input and output data as sequences of lines, each terminated by a
zero byte (the ASCII NUL character) instead of a newline. Like the -Z or
--null option, this option can be used with commands like sort -z to
process arbitrary file names.
-o, --only-matching
Print only the matched (non-empty) parts of a matching line, with each
such part on a separate output line.
-E, --extended-regexp
Interpret PATTERN as an extended regular expression (ERE, see below).
正则表达式查找单词define
,后跟 0 个或多个非}
字符 ( [^}]*
),然后host_name yyyyyyyyy991
是所有内容,直到第一个}
( ) 加上下一个与换行符匹配的.+?
字符(最后一个)。.
然而,就我个人而言,我会使用 Perl 的段落模式来做这样的事情:
$ perl -00 -ne 'print if /yyyyyyyyy991/' file
define host{
host_name yyyyyyyyy991
use aix-server
alias
hostgroups +bu-automotiveprd,screen-automotiveprd2
address YYY.YYY.YYY.YYY
}
指示-00
将perl
输入文件作为段落读取,因此每个记录都是一个段落(由 2 个连续\n
字符定义)而不是一行。然后,-ne
意思是“读取每个输入记录并对其应用给定的脚本-e
”。脚本本身只是打印与所需模式匹配的任何记录。
答案3
假设您的配置文件名为 config.dat 并且它有标准格式。这意味着 yyyyyyyyy991 之前只有一行,后面只有五行,那么这个命令将帮助您获得所需的输出:
grep -B 1 -A 5 "yyyyyyyyy991" config.dat
define host{
host_name yyyyyyyyy991
use aix-server
alias
hostgroups +bu-automotiveprd,screen-automotiveprd2
address YYY.YYY.YYY.YYY
}
从grep
男人:
Context control flage:
-B, --before-context=NUM print NUM lines of leading context
-A, --after-context=NUM print NUM lines of trailing context
如果文件 config.dat 是另一种解决方案不标准,这意味着关键字“yyyyyyyyy991”在每个部分中不遵循相同的模式,然后awk
可以按如下方式执行您想要的操作:
awk -v RS='' '/host_name yyyyyyyyy991/' config.dat
RS= 将输入记录分隔符从换行符更改为空行。如果记录中的任何字段包含 /host_name yyyyyyyyy991/ 则打印该记录。
如果 RS 为空,则记录由由一个或多个空行组成的序列分隔,前导或尾随空行不应导致输入的开头或结尾处出现空记录,并且 a 应始终是字段分隔符,不管FS的值是多少。
输出段落不会被分隔,因为输出分隔符仍然是单个换行符。为了确保输出段落之间有空行,请将输出记录分隔符设置为两个换行符。
答案4
使用sed
:
sed 'H;/^define host{$/h;/^}/{g;/host_name yyyyyyyyy991\n/p};d' file
一步步:
H # append line to hold space
/^define host{$/h # start of entry: copy to hold space (overwrites previous content)
/^}/{ # end of entry:
g # retrieve whole entry from hold space
/host_name yyyyyyyyy991\n/p # if host matched, display the whole entry
}
d # no other output