tags:

views:

142

answers:

4

Hi all,

How can I check for the next line while running in a current loop? Also, how can I move C comments to end of the line for a table?

I have a file like this:

array_table=
{
    /* comment 1*/ (unsigned int a); 
    /* comment 2*/ (unsigned int b); 
    /* comment 3*/ (unsigned int c); 
    /* comment 4*/ (unsigned int d);
}

My intention is to move those comments to the end of the line like:

array_table=
{
    (unsigned int a); /* comment 1*/
    (unsigned int b); /* comment 2*/
    (unsigned int c); /* comment 3*/ 
    (unsigned int d); /* comment 4*/
}

How can I do that in Perl? Can anyone help me with the Perl code?

+1  A: 

Something like this should work:

while (<>) {
    chomp;
    if ($_ =~ m%^(.*)/\*(.*)\*/(.*)$%) {
            printf "%s%s/*%s*/%s", $1, $3, $2, $/;
    } else {
            print $_ . $/;
    }
}

The bracketed expressions match anything before the comment, the comment itself, and anything left after the comment. The printf then recomposes them in the right order.

Alnitak
why you chomp it and not keep it unaffected?
Hynek -Pichi- Vychodil
so that $3 definitely doesn't include the newline - it's probably superfluous.
Alnitak
btw the perlre man page is ambiguous - for '$' is says "match the end of the line (or before newline at the end)". It _doesn't_ say match $/, so its unspecified what happens in the input contains \r\n
Alnitak
+1  A: 

OK - to restate what I think you are asking for, you want to parse a file, and look for assigments of the form

foo=
   {
       ....
   }

and within the block, you want to move the comments to the end of the line. There are a number of ways to do this, the most elegant is usually related to what else you are doing in the loop. The one that springs to mind is just to remember the fact that the last line contained an '=' and use that fact when matching for '{' at the start of a line. Using one of my favourite perl constructs, the range operator in scalar context. So this would give...

my $last_line_an_assignment = 0;
while (<DATA>)
{
    if (($last_line_an_assignment && m!^\s*{!) .. m!^\s*}!)
    {
        s!(/\*.*?\*/)\s*(.*)$!$2 $1!;
    }

    print $_;

    $last_line_an_assignment = m!=!;
}

__DATA__

  /* comment other */ (unsigned int a); 

  other_assignment=
     /* not a table */ 12;

  array_table=
      {
        /* comment 1*/ (unsigned int a); 
        /* comment 2*/ (unsigned int b); 
        /* comment 3*/ (unsigned int c); 
        /* comment 4*/ (unsigned int d);
      }

  /* comment other */ (unsigned int a);

You can either print the data to another file, or you can update the files in place, using the '-i' option to perl

local (@ARGV) = ($filename);
local ($^I) = '.bak';
while (<>)
{
    # make changes to line AND call print
}

This causes perl to make a backup of $filename (with extention '.bak'), and then all print calls in the loop will overwrite the contents if the file - for more information see the '-i' option in the "perlrun" manual page.

Beano
i have a .c files in dat am takin a file one by one and searching for a table and i have to move the comments that is present in front to the end... this is one i want.... i asked for to know the next line cos while runnin a loop am collecting each line every time and checking for = at last... and i wan to knw hw to check for { which is present at next line in the table.... thanks if u solve this prblm...
lokesh
A: 

If you want change only comments inside array_table statement:

perl -pe's,^(\s*)(/\*.*?\*/)\s*(.*?)[ \t]*$,$1$3 $2, if/^\s*array_table\s*=/../^\s*\}/'

otherwise simply:

perl -pe's,^(\s*)(/\*.*?\*/)\s*(.*?)[ \t]*$,$1$3 $2,'
Hynek -Pichi- Vychodil
A: 

Use Regexp::Common rather than rolling your own. E.g.

use Regexp::Common;

while ($_ = <DATA>) {
    chomp;
    if (s/(^\s*)($RE{comment}{C})//) {
        print $1, $_, $2, "\n";
    }
    else {
        print $_, "\n";
    }
}

__DATA__
              /* comment other */ (unsigned int a); 

              other_assignment=
                 /* not a table */ 12;

              array_table=
                  {
                    /* comment 1*/ (unsigned int a); 
                    /* comment 2*/ (unsigned int b); 
                    /* comment 3*/ (unsigned int c); 
                    /* comment 4*/ (unsigned int d);
                  }

              /* comment other */ (unsigned int a);
xcramps