0

I need to grep a particular value from each line shown below:

ABC_ROOT|/home/test/test_1/ABC/ABC-012/ABC04.16.103/lnx86
DEF_ROOT|/home/test/test_2/DEF/DEF192/DEF19.20.100/lnx86
GHI_ROOT|/home/test/test_3/GHI/GHI19.10.199/lnx86/tools.lnx86
JKL_ROOT|/home/test/test_4/JKL/JKL19.00.000/lnx86
ABC_ROOT|/home/test/test_1/ABC/ABC-012/ABC04.16.103/lnppc
DEF_ROOT|/home/test/test_2/DEF/DEF192/DEF19.20.100/lnppc

From the above lines, I want to grep the values that has version numbers ABC04.16.103, DEF19.20.100, GHI19.10.199, JKL19.00.000 for lnx86 only.

I tried the below regex but it gives me result for both lnx86 and lnppc:

 /([A-Z]{3}\d{2}\.\d{2}\.\d{3})/
2
  • Is this all you need? Commented Mar 1, 2020 at 16:23
  • Yes can you please help. Commented Mar 1, 2020 at 16:54

3 Answers 3

4

A good pattern includes everything you need to match the interesting data but also enough information to exclude the uninteresting data. Since you want only the lines with lnx86, make that part of your pattern. I've written this with the /x to spread out the pattern to make it easier to grok:

while( <DATA> ) {
    next unless m|
        /
        ( [A-Z]{3} \d{2} \.\d{2} \.\d{3} )   # $1
        /
        lnx86
        (?: / | \Z ) # another slash or end of string
        |x;

    print;
    }

__END__
BC_ROOT|/home/test/test_1/ABC/ABC-012/ABC04.16.103/lnx86
DEF_ROOT|/home/test/test_2/DEF/DEF192/DEF19.20.100/lnx86
GHI_ROOT|/home/test/test_3/GHI/GHI19.10.199/lnx86/tools.lnx86
JKL_ROOT|/home/test/test_4/JKL/JKL19.00.000/lnx86
ABC_ROOT|/home/test/test_1/ABC/ABC-012/ABC04.16.103/lnppc
DEF_ROOT|/home/test/test_2/DEF/DEF192/DEF19.20.100/lnppc

This selects the lines that you want:

BC_ROOT|/home/test/test_1/ABC/ABC-012/ABC04.16.103/lnx86
DEF_ROOT|/home/test/test_2/DEF/DEF192/DEF19.20.100/lnx86
GHI_ROOT|/home/test/test_3/GHI/GHI19.10.199/lnx86/tools.lnx86
JKL_ROOT|/home/test/test_4/JKL/JKL19.00.000/lnx86

You can generalize this a bit so you can choose a different tool later. Use quotemeta to ensure that nothing in the value is a regex meta-character (unless that's what you want):

my $tool = quotemeta( 'lnx86' );

while( <DATA> ) {
    next unless m|
        /
        ( [A-Z]{3} \d{2} \.\d{2} \.\d{3} )   # $1
        /
        $tool
        (?: / | \Z ) # another slash or end of string
        |x;

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

Comments

1

Just add positive lookahead at the end to make it match only lnx86 like this: /([A-Z]{3}\d{2}\.\d{2}\.\d{3})(?=/lnx86)/. This way it only match your pattern if it followed by the /lnx86 string.

2 Comments

It gave the below error: Unmatched ( in regex; marked by <-- HERE in m/([A-Z]{1,11}\d{2}\.\d{2}\.\d{3})( <-- HERE ?=/ at <filename>
@Pulkit you might have some copy paste error since the pattern has the matching ).
0

Is it what you after?

use strict;
use warnings;
use feature 'say';

for (<DATA>) {                     # walk through data
    say $1 if m!([^/]+)/lnx86!;    # match pattern and output
}

__DATA__
ABC_ROOT|/home/test/test_1/ABC/ABC-012/ABC04.16.103/lnx86
DEF_ROOT|/home/test/test_2/DEF/DEF192/DEF19.20.100/lnx86
GHI_ROOT|/home/test/test_3/GHI/GHI19.10.199/lnx86/tools.lnx86
JKL_ROOT|/home/test/test_4/JKL/JKL19.00.000/lnx86
ABC_ROOT|/home/test/test_1/ABC/ABC-012/ABC04.16.103/lnppc
DEF_ROOT|/home/test/test_2/DEF/DEF192/DEF19.20.100/lnppc

Output

ABC04.16.103
DEF19.20.100
GHI19.10.199
JKL19.00.000

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.