1

I have a variable with some blob of text in it

$foo = "
    Garbage directory
    /test/this/is/a/directory
    /this/is/another/foo\nThisd is is\nDrop stuff testing\nRandom stuff emacs is great";

How do I use regex to get the line that is /test/this/is/a/directory

I tried this:

my $foo = "
    Garbage directory
    /test/this/is/a/directory
    /this/is/another/foo\nThisd is is\nDrop stuff testing\nRandom stuff emacs is great";
$foo =~ /^\/test.*$/;
print "\n$foo\n";

But this just keeps on printing the whole blob of text.

  • What defines a directory in your case ? I.e. why is `/this/is/another/foo` not a dir? Otherwise just change your expression to `$foo =~ ~^\s*/test.*$~m;` – Jan May 23 '18 at 20:24

3 Answers3

1

Change your expression to

$foo =~ m~^\s*/test.*$~m;

See a demo on regex101.com.


This uses other delimiters (~) so that you don't need to escape the /, additionally whitespaces (\s*) and turns on the multiline mode (m).

Borodin
  • 126,100
  • 9
  • 70
  • 144
Jan
  • 42,290
  • 8
  • 54
  • 79
  • @Borodin: Are really two `m`s needed ? (not a `Perl` guy here). – Jan May 23 '18 at 20:32
  • 2
    If you change the delimiter then you need to explicitly name the operator `m~...~`. It's optional only if you use the default slashes. – Borodin May 23 '18 at 20:33
1

The OP seems to want the specified line to be printed, rather than the whole blob of text. For this, we need to modify Jan's answer to capture and extract the actual match.

my $foo = "
    Garbage directory
    /test/this/is/a/directory
    /this/is/another/foo\nThisd is is\nDrop stuff testing\nRandom stuff emacs is great";
$foo =~ m~^(\s*/test.*)$~m;
$foo = $1;
print "\n$foo\n"

Output:

/test/this/is/a/directory
merlin2011
  • 71,677
  • 44
  • 195
  • 329
-1

Your regular expression should be:

/\/test.*\n/

The reason is because you are matching the entire text and there's no limit to the end of the line. You'll need to express that you want the match to the next new line. This regular expression includes the newline in the match though.

With regular expressions there are different ways to do it so it depends on the context of what you're trying to accomplish. You could add the m modifier at the end. What this will do is treat the string as multiple lines so you can then use ^$ with each line instead of the entire text. Also using the m multiline modifier will not result in a match that includes the newline.

/\/test.*/m would suffice.

For more info: https://perldoc.perl.org/perlre.html

Furthermore print "$foo"; WILL NOT print the match because =~ operator returns a true or false value and does not reassign the variable to the match. You'll need to change the regex for pattern matching and print the first match:

$foo =~ /(\/test.*)/m;
print $1;
Paul Carlton
  • 2,785
  • 2
  • 24
  • 42
  • 1
    why do we need the `\n`? – Matt.G May 23 '18 at 20:27
  • my comment was purely based on the `\n` in the regex, as it'll capture the linefeed as well as part of the match, which is not the OP's requirement – Matt.G May 23 '18 at 20:46
  • The requirement is to match that line. Technically you could argue the newline is a subtlety that in most cases people wouldn't want to match and it is not explicitly stated in the question. But that's kinda nit picky for a down vote. – Paul Carlton May 23 '18 at 20:51
  • 1
    This worked perfectly for me thanks. I will accept this as it explains why my attempt failed as well. – Justin Kaipada May 23 '18 at 23:36