1

I have configuration file like:

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
}

I would like to search host_name, and if it is matching, output should be like below:

Example - Let's suppose I would like to search yyyyyyyyy991 host.

Then the output must be like below:

define host{
        host_name yyyyyyyyy991
        use aix-server
        alias
        hostgroups +bu-automotiveprd,screen-automotiveprd2
        address YYY.YYY.YYY.YYY
}
  • Please do not revert formatting changes. Without code formatting the question is difficult to read and understand. – sebasth Sep 24 '18 at 8:22
3

try this,

perl -0777 -ne '/([^\n]*{[^}]*(yyyyyyyyy991)[^}]*})/ && print "$1\n"' file

Explanation:

  • perl -0777 Run perl and slurp the whole file as one line.
  • -ne for each line (n), execute (e) the following.
  • /(pattern)/ && print "$1\n" match a regex pattern and add it as first matching group ($1), then print it.

The Pattern:

  • [^\n]*{ ... } Match anything from the beginning of a line including "{" to the next "}"
  • With the ... being [^}]*(yyyyyyyyy991)[^}]*:
    • Match any character that is not }
    • must include yyyyyyyyy991 somewhere.
2

If your grep supports it, you can use the -z option to make it slurp the entire file:

$ 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
}

The grep options used are (from the man page of 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).

The regular expression looks for the word define, followed by 0 or more non-} characters ([^}]*), then host_name yyyyyyyyy991 and then everything until the first } (.+?) plus the next character (the final .) which will match the newline.


Personally, however, I would do this sort of thing using perl's paragraph mode:

$ 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
}

The -00 tells perl to read the input file as paragraphs, so each record is a paragraph (defined by 2 consecutive \n characters) instead of a line. Then, the -ne means "Read each input record and apply the script given by -e to it". The script itself simply prints any records matching the desired pattern.

  • 1
    not sure grep is working! – user308606 Sep 24 '18 at 8:49
  • grep --version grep (GNU grep) 2.20 Copyright (C) 2014 Free Software Foundation, Inc. – user308606 Sep 24 '18 at 8:52
  • @terdon. it is really strange. not working at all on my side? I am using Centos 7 – user308606 Sep 24 '18 at 9:00
  • @Kasper according to this man page I found for CentOS 7, the grep it ships with doesn't have the -z option. That's why I have "if your grep supports it" as the first sentence of the answer. – terdon Sep 24 '18 at 9:05
  • grep --help I see -Z, --null print 0 byte after FILE name – user308606 Sep 24 '18 at 9:06
2

Let's say your configuration file is called config.dat and it has standard format. Meaning you only have one line before yyyyyyyyy991 and five lines after it, then this command will help you to get the output you want:

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
}

From grep man:

Context control flage:
  -B, --before-context=NUM  print NUM lines of leading context
  -A, --after-context=NUM   print NUM lines of trailing context

Another solution in case the file config.dat is not standard, meaning the key word "yyyyyyyyy991" doen't follow the same pattern in every section, then awk can do what you want as follows:

 awk -v RS='' '/host_name yyyyyyyyy991/' config.dat

RS= changes the input record separator from a newline to blank lines. If any field in an record contains /host_name yyyyyyyyy991/ print the record.

According to posix

If RS is null, then records are separated by sequences consisting of a plus one or more blank lines, leading or trailing blank lines shall not result in empty records at the beginning or end of the input, and a shall always be a field separator, no matter what the value of FS is.

The output paragraphs will not be separated since the output separator remains a single newline. To ensure that there is a blank line between output paragraphs, set the output record separator to two newlines.

  • 1
    Many thanks, Goro :) It is working in this scenario but it is not mandatory that "host_name yyyyyyyyy991" line would be 2nd line, line sequence can be changed. – Rakesh Kumar Sep 24 '18 at 8:35
  • @Rakesh Kumar. see my edits ;-) – user88036 Sep 24 '18 at 9:14
0

Using sed:

sed 'H;/^define host{$/h;/^}/{g;/host_name yyyyyyyyy991\n/p};d' file

Step-by-step:

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.