12

I have the following script i wrote in perl that works just fine. But i am trying to achieve the same thing using bash.

#!/usr/bin/perl

use 5.010;
use strict;

INIT {
    my $string = 'Seconds_Behind_Master: 1';
    my ($s) = ($string =~ /Seconds_Behind_Master: ([\d]+)/);
    if ($s > 10) {
        print "Too long... ${s}";
    } else {
        print "It's ok";
    }
}

__END__

How can i achieve this using a bash script? Basically, i want to be able to read and match the value at the end of the string "Seconds_Behind_Master: N" where N can be any value.

2
  • 3
    Running the code in an INIT block seems confusing and distracting. If it's the contents of the block you want to have translated, just pare it down to that. See also minimal reproducible example Commented Jun 21, 2016 at 4:59
  • tripleee, iwant to implement the logic in bash, hence the use of the init in a perl script is not so important. So yes, just focus on the inner code content please. Commented Jun 21, 2016 at 7:30

3 Answers 3

16

You can use regular expression in bash, just like in perl.

#!/bin/bash

STRING="Seconds_Behind_Master: "

REGEX="Seconds_Behind_Master: ([0-9]+)"

RANGE=$( seq 8 12 )

for i in $RANGE; do
    NEW_STRING="${STRING}${i}"
    echo $NEW_STRING;

    [[ $NEW_STRING =~ $REGEX ]]
    SECONDS="${BASH_REMATCH[1]}"
    if [ -n "$SECONDS" ]; then
        if [[ "$SECONDS" -gt 10 ]]; then
            echo "Too Long...$SECONDS"
        else
            echo "OK"
        fi
    else
        echo "ERROR: Failed to match '$NEW_STRING' with REGEX '$REGEX'"
    fi
done

Output

Seconds_Behind_Master: 8
OK
Seconds_Behind_Master: 9
OK
Seconds_Behind_Master: 10
OK
Seconds_Behind_Master: 11
Too Long...11
Seconds_Behind_Master: 12
Too Long...12

man bash #BASH_REMATCH

Sign up to request clarification or add additional context in comments.

Comments

12

You can use a tool for it e.g. sed if you want to stay with regexps:

#!/bin/sh
string="Seconds_Behind_Master: 1"
s=`echo $string | sed -r 's/Seconds_Behind_Master: ([0-9]+)/\1/g'`
if [ $s -gt 10 ]
then
    echo "Too long... $s"
else
    echo "It's OK"
fi

2 Comments

Huh? Bash has glob-based string substitution which is quite capable of solving this.
The question asks about regexp, and I assumed bash doesn't have that, but as I can see from other responses it actually does. As for glob - those are not regexps as it was asked for in the title of question.
2

The specific case of "more than a single digit" is particularly easy with just a pattern match:

case $string in
   *Seconds_Behind_Master: [1-9][0-9]*) echo Too long;;
   *) echo OK;;
esac

To emulate what your Perl code is doing more closely, you can extract the number with simple string substitutions.

s=${string##*Seconds_Behind_Master: }
s=${s%%[!0-9]*}
[ $s -gt 10 ] && echo "Too long: $s" || echo OK.

These are glob patterns, not regular expressions; * matches any string, [!0-9] matches a single character which is not a digit. All of this is Bourne-compatible, i.e. not strictly Bash only (you can use /bin/sh instead of /bin/bash).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.