I am trying the code below and hoping to get result as 0 (i.e. $? -eq 0) but for some reason it always fails:

echo "INBOUND_PATH|/tmp" | grep -E '^\(INBOUND_PATH\)\|\(.*\)$';

echo $?

The reason I wanted to create a back reference is because if the string format was valid then I would cut out the directory with following command:

g_inboundDir=grep -E 's/^\(INBOUND_PATH\)\|(.*)$/\2';

  • 2
    you've escaped the ( so its looking for a line starting with (INBOUND_PATH etc. – steve Jul 8 '17 at 16:59
  • You need to use a look-ahead with grep -P. – jordanm Jul 8 '17 at 17:10

Bridging the gap and all answers together, and also looking at the man page of grep (man grep) , we have two main kinds of regular expressions: Basic Regex and Extended Regex.

According to man grep :

Basic vs Extended Regular Expressions
In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions \?, +, {, \|, (,and ).

In other words you can capture groups with single grep using escaped () like grep \(....\) or if you use grep -E or egrep you dont need to escape parenthesis : egrep '(....)'

Same rules apply to sed. A simple sed understands basic regular expressions thus you need escaping to capture groups : sed 's/\(....\)\(...\)/\2/' or you can enable extended regex support in sed with -E or -r switch (depending on sed implementation) : sed -E 's/(...)(...)/\2/'

As a result all bellow commands are valid:

$ echo "INBOUND_PATH|/tmp" | grep '^\(INBOUND_PATH\)|\(.*\)$';echo $?

$ echo "INBOUND_PATH|/tmp" | egrep '(INBOUND_PATH)\|(.*)$';echo $?

$ echo "INBOUND_PATH|/tmp" | sed 's/^\(INBOUND_PATH\)|\(.*$\)/\2/'

$ echo "INBOUND_PATH|/tmp" | sed -E 's/(INBOUND_PATH)\|(.*)$/\2/'

Mind the opossite handling of special symbols in different Regexes.

For example see the handling of pipe | symbol in above commands:
In basic regex (BRE):
You don't need to escape pipe symbol to match a literal pipe symbol.
Escaping pipe symbol in BRE, will be considered as an OR operator (which accidentaly will work in your case).

Similarilly , in BRE you don't need to escape parenthesis ( ) to match a literal parenthesis but you need to escape parenthesis to capture a group.

In extended regex (ERE):
You need to escape the pipe symbol in order to be matched literally, since by default in ERE pipe symbol is treated as OR operator (opposite handling compared to BRE)

Similarilly in ERE you need to escape parenthesis to match a literall parenthesis (, since by default parenthesis in ERE is used to capture groups.

  • 1
    FWIW, omitting the closing / in s/.../.../ is Vim syntax, which has its own regex dialect, different from both BRE and ERE. – Satō Katsura Jul 9 '17 at 9:20
  • @AlluSingh You are Welcome. Since you are new here, you might need to accept one of the answers posted in your question. See unix.stackexchange.com/help/accepted-answer – George Vasiliou Jul 9 '17 at 20:35

The basic check for the string doesn't have to be quite so complicated:
echo "INBOUND_PATH|/tmp" | grep -q '^INBOUND_PATH|.*$'

I assume you meant the second one to be sed, not grep:
g_inboundDir=$(echo "INBOUND_PATH|/tmp" | sed 's/^\(INBOUND_PATH\)|\(.*$\)/\2/')

Note the lack of -E. I also fixed the missing trailing /.


You're adding -E which is an extended regular expresions

-E, --extended-regexp Interpret PATTERN as an extended regular expression (ERE, see below).

And still escaping it. It is not needed.

$ echo "INBOUND_PATH|/tmp" | grep -E '^(INBOUND_PATH)\|(\/.*)'; echo $?

On the other hand, you can use egrep with the same effect (without -E).

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.