Dirk80 has asked for the wisdom of the Perl Monks concerning the following question:

I have a big text file. I'm interested only in the beginning tag and the text between a beginning and an end tag.

textfile.txt

Any text is in this document. But I'm only interested in the text between a beginning and an end tag +. BEGIN_TAG_110 In this text I'm interested in. It can consist of several lines. Until the end tag. END_TAG and any other things I'm not interested in until the next begi +nning tag starts. Any other text. BEGIN_TAG_237 I need this text. END_TAG More text ...

The result should be like this:

# BEGIN_TAG_110: # In this text I'm interested in. # It can consist of several lines. Until the end tag. # # BEGIN_TAG 237: # I need this text.

I'd like to have the beginning tag as the key of a hash and the corresponding text as its string value.

I tried this regular expression:

m/^.*BEGIN_TAG_(\d+)(.*)END_TAG.*/s;

But it works only with the last one. It seems to be too greedy. But my main problem is how not to get only one, but all.

I'm really interested in how it could be done in a good manner or for any hints from you. Thank you!!

Replies are listed 'Best First'.
Re: Get text between start and end tag
by hippo (Archbishop) on Feb 27, 2024 at 11:12 UTC
    It seems to be too greedy.

    Quite right. You can make it less greedy by using the ? character.

    #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; my $text = <<EOT; Any text is in this document. But I'm only interested in the text between a beginning and an end tag +. BEGIN_TAG_110 In this text I'm interested in. It can consist of several lines. Until the end tag. END_TAG and any other things I'm not interested in until the next begi +nning tag starts. Any other text. BEGIN_TAG_237 I need this text. END_TAG More text ... EOT my %res = $text =~ /BEGIN_TAG_(\d+)(.*?)END_TAG/sg; print Dumper (\%res);

    That should get you started anyway.


    🦛

      Thank you very much!! This solved my problem. I just slurp the text file in a string variable and then apply your regex which I can now fully understand.

      #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; my $file = 'textfile.txt'; open my $fh, '<', $file or die; $/ = undef; my $text = <$fh>; close $fh; my %res = $text =~ /BEGIN_TAG_(\d+)(.*?)END_TAG/sg; print Dumper (\%res);
Re: Get text between start and end tag
by Marshall (Canon) on Feb 27, 2024 at 11:27 UTC
    The key tutorial you seek is Flipin good, or a total flop?
    use strict; use warnings; #https://www.perlmonks.org/?node_id=525392 my $lineNUM; while (<DATA>) { if ($lineNUM = /^BEGIN_TAG/.../^END_TAG/ ) { print "#$_" if $lineNUM =~ /^\d+$/; print "#\n" if $lineNUM =~ /E0/; } } =Prints #BEGIN_TAG_110 #In this text I'm interested in. #It can consist of several lines. Until the end tag. # #BEGIN_TAG_237 #I need this text. # =cut __DATA__ Any text is in this document. But I'm only interested in the text between a beginning and an end tag +. BEGIN_TAG_110 In this text I'm interested in. It can consist of several lines. Until the end tag. END_TAG and any other things I'm not interested in until the next begi +nning tag starts. Any other text. BEGIN_TAG_237 I need this text. END_TAG More text ...

      Cool solution. Interesting tutorial. Thank you very much!!!

Re: Get text between start and end tag
by tybalt89 (Monsignor) on Feb 27, 2024 at 15:26 UTC

    Or if you don't wish to read the whole file into memory, you can always just read in a section:

    #!/usr/bin/perl use strict; use warnings; my %res; { # for localizing $/ local $/ = 'END_TAG'; /BEGIN_TAG_(\d+)(.*)END_TAG/s and $res{$1} = $2 while <DATA>; } use Data::Dump 'dd'; dd \%res; __DATA__ Any text is in this document. But I'm only interested in the text between a beginning and an end tag +. BEGIN_TAG_110 In this text I'm interested in. It can consist of several lines. Until the end tag. END_TAG and any other things I'm not interested in until the next begi +nning tag starts. Any other text. BEGIN_TAG_237 I need this text. END_TAG More text ...

    Outputs:

    { 110 => "\nIn this text I'm interested in.\nIt can consist of several + lines. Until the end tag.\n", 237 => "\nI need this text.\n", }
Re: Get text between start and end tag
by perlfan (Parson) on Feb 29, 2024 at 05:08 UTC
    split takes a regex as it's separator.