Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to write some Bash that can verify that a string exists in a configuration file. I can't change the file format, it belongs to a different application.

The file is subdivided into groups named by strings in square brackets.

This should be a success:

[group1]
MyParameter
junk1
junk2

[group2]
junk3
junk4

This should be an error:

[group1]
junk1
junk2

[group2]
MyParameter
junk3
junk4

I can do a grep -q to verify that MyParameter exists in the file, but if it's located in some other group and not group1, then I'm still busted.

If MyParameter existed in both groups, I wouldn't care enough to flag an error, as long as it existed in group1.

I can't depend on line numbers (head, tail, etc). Also, I'd be happier if it was generic enough that it doesn't depend on the name of group2 (the script would just know that if it found another line beginning and ending with square brackets, that terminates the previous group).

share|improve this question
    
Is MyParameter alway immediately after [groupX] lines, or it does not have any specific position? –  ztank1013 Nov 4 '11 at 21:23
    
No specific position... –  twblamer Nov 4 '11 at 21:31
    
Ok, take a look at my answer, it should work. –  ztank1013 Nov 4 '11 at 21:40

4 Answers 4

up vote 6 down vote accepted

Whenever faced with a text processing problem, some people say “let's use awk”. More often than not, they have a solution.

awk '
    /^\[.*\]$/ {group = $0}
    group == "[group1]" && $1 == "MyParameter" {found=1; exit}
    END {exit !found}
'
share|improve this answer
    
Nice one. What it does (as explanation to the uninitiated): it remembers the last seen group name (the one in square brackets) while going through the file. And when it encounters the parameter together with the correct group it sets the flag found to 1. At the end it exits with the appropriate status code (0 if the param has been found in the correct group). –  Axel Knauf Nov 5 '11 at 16:16
    
Thanks, it looks like this will do... –  twblamer Nov 7 '11 at 21:44

With GNU sed you can do

sed -n '/\[group1\]/,/\[group2\]/{/MyParameter/p}' input-file

that will write MyParameter only when it is in the group1 section. If the section after group1 is not always group2, you can substitute group2 with .*.

share|improve this answer
    
(+1) /^MyParameter&/ will resolve an embedded pattern match (eg. MyParameters) –  Peter.O Nov 6 '11 at 8:07
if [ `egrep 'MyParameter|^\[.*\]$' file.conf | head -2 | tail -1` == "MyParameter" ]
then 
  echo Success
else 
  echo Failure
fi
share|improve this answer
    
This works, when [group1] is the first group, otherwise it returns Failure.. I wonder if that was the question's intention ? –  Peter.O Nov 6 '11 at 8:08
    
@fered Well we should ask to the question's author... –  ztank1013 Nov 6 '11 at 9:53

Here's a Perl script that should do the job:

#!/usr/bin/perl

use strict;
use warnings;

die "Usage: $0 group pattern [file...]\n" if scalar @ARGV < 2;

my $group = shift;
my $pattern = shift;

my $curr_group = undef;
my $matched = 0;
while (<>) {
    if (/^\[(.*)\]/) {
        $curr_group = $1;
    }
    else {
        if (defined $curr_group and 
            $curr_group eq $group and 
            /$pattern/) 
        {   
            print "Match\n";
            $matched = 1;
        }
    }
}

if (not $matched) {
    print "No match\n";
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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