ssr1012
ssr1012

Reputation: 2589

In array listitem how to store values with comma separation and end with dot using perl

 use strict;
 use warnings;

 my $tmp = join "\n", <DATA>;
 my @biblables = ();

List items will be fetched and storing into @biblables in a while loop

 while($tmp=~m/\\bibitem\[([^\[\]]*)\]{([^\{\}]*)}/g)
 {
      push(@biblables, "\\cite{$2}, ");
 }

 print @biblables;

While printing this we are getting the output like as:

 \cite{BuI2001},\cite{BuI2002},\cite{BuI2003},\cite{BuI2004},\cite{BuI2005},\cite{BuI2006},

However we need the output like this

 \cite{BuI2001},\cite{BuI2002},\cite{BuI2003},\cite{BuI2004},\cite{BuI2005},\cite{BuI2006}.

Hence we can use post regex to insert dot at the end of the listitem in array

 while($tmp=~m/\\bibitem\[([^\[\]]*)\]{([^\{\}]*)}/g)
 {
      my $post = $';
      if($post!~m/\\bibitem\[([^\[\]]*)\]{([^\{\}]*)}/)
      {  push(@biblables, "\\cite{$2}.");  }
      else {  push(@biblables, "\\cite{$2}, ");  }
 }

 print @biblables;

Could you please advise me if there is short way to get this output

#
__DATA__    
\bibitem[{BuI (2001)}]{BuI2001}    
\bibitem[{BuII (2002)}]{BuI2002}    
\bibitem[{BuIII (2003)}]{BuI2003}    
\bibitem[{BuIV (2004)}]{BuI2004}    
\bibitem[{BuV (2005)}]{BuI2005}    
\bibitem[{BuVI (2006)}]{BuI2006}

Upvotes: 0

Views: 483

Answers (3)

zdim
zdim

Reputation: 66899

If you read from a filehandle you can use eof to determine that you are on the last line, at which point you replace the comma by the dot in the last element. This allows you to build the array completely in the loop, as required.

use warnings;
use strict;

open my $fh, '<', 'bibitems.txt';

my @biblabels;

while (<$fh>) {
    push @biblabels, "\\cite{$2}," if /\\bibitem\[([^\[\]]*)\]{([^\{\}]*)}/;
    $biblabels[-1] =~ tr/,/./      if eof;
}

print "$_ " for @biblabels;
print "\n";

This prints your desired output.

The oef returns true if the next read will return end-of-file. This means that you've just read the last line, which got put on the array if it matched. This function is rarely needed but here it seems to find a fitting purpose. Note that eof and eof() behave a little differently. Please see the eof page.


If the other capture in the regex is meant to be used change the above to if (...) { ... }. Note that what is in {} is in Latex called citation keys, while the (optional) labels are things inside []. I'd go with the array name of @citkeys for clarity.

Upvotes: 1

user557597
user557597

Reputation:

If you're determine to add the comma's and dots to the elements when
matching in the regex while loop, it can be done like this.

Since you don't know the total matches yet, just keep a reference to
the most recently pushed element.
Then append the , or . as needed.

Code

use strict;
use warnings;

$/ = undef;

my $tmp = <DATA>;
my @biblables = ();
my $ref = undef;

while( $tmp =~ /\\bibitem\[([^\[\]]*)\]{([^\{\}]*)}/g )
{
   $$ref .= ", " if defined $ref;
   $ref = \$biblables[ push(@biblables,"\\cite{$2}") ];
}
$$ref .= "." if defined $ref;

print @biblables;

__DATA__    
\bibitem[{BuI (2001)}]{BuI2001}    
\bibitem[{BuII (2002)}]{BuI2002}    
\bibitem[{BuIII (2003)}]{BuI2003}    
\bibitem[{BuIV (2004)}]{BuI2004}    
\bibitem[{BuV (2005)}]{BuI2005}    
\bibitem[{BuVI (2006)}]{BuI2006}

Output

\cite{BuI2001}, \cite{BuI2002}, \cite{BuI2003}, \cite{BuI2004}, \cite{BuI2005}, \cite{BuI2006}.

Upvotes: 1

stevieb
stevieb

Reputation: 9306

You can add the comma and period after the fact:

while($tmp=~m/\\bibitem\[([^\[\]]*)\]{([^\{\}]*)}/g){
   push(@biblables, "\\cite{$2}");
}

print join ', ', @biblables;
print ".\n";

Upvotes: 7

Related Questions