开发者

How can I change 'long' to 'int' without changing 'long long' using perl/awk/etc

I want to change all the longs to ints (in preparation for 64 bit code). I have a perl line that does:

s/(\s*long\s+)(?!long)/ int /g

which comes close. It change开发者_运维百科s long to int and long long to long int.

Any editing method is good as long as it can be scripted or operate on multiple files.

*Sample:  input              desired output*
   long abd;                   int abd;
int longname;               int longname;
int reallylongname;         int reallylongname;
float reallylong longname;  float reallylong longname;
double namelong             double namelong
long abc long               int abc int
long long abc               long long abc
long    long hhhh           long    long hhhh
long long hhhh              long long hhhh
long abd( long kjhh         int abd( int kjhh


The following would be ideal if variable width lookbehinds were supported:

s/
   (?<! \b long \s+)
   \b long \b
   (?! \s+ long \b)
/int/xg

That leaves you with the messier:

s/
   \b ( (?: long \s+ )* ) long \b
/
   length($1) ? $1."long" : "int"
/xeg

Update: This works as well:

s/
   (?<! \b long )
   (?<! \s ) \s* \K
   \b long \b
   (?! \s+ long \b)
/int/xg

Update: Tested using:

use strict;
use warnings;

use Test::More;

sub fix {
   my ($s) = @_;
   $s =~ s/
      \b ( (?: long \s+ )* ) long \b
   /
      length($1) ? $1."long" : "int"
   /xeg;
   return $s;
}

my @tests = (
   [ '   long abd;',                '   int abd;'                ],
   [ 'int longname;',               'int longname;'              ],
   [ 'int reallylongname;',         'int reallylongname;'        ],
   [ 'float reallylong longname;',  'float reallylong longname;' ],
   [ 'double namelong',             'double namelong'            ],
   [ 'long abc long',               'int abc int'                ],
   [ 'long long abc',               'long long abc'              ],
   [ 'long    long hhhh',           'long    long hhhh'          ],
   [ 'long long hhhh',              'long long hhhh'             ],
   [ 'long abd( long kjhh',         'int abd( int kjhh'          ],
);

plan tests => 0+@tests;

for (@tests) {
   my ($i,$e) = @$_;
   my $g = fix($i);
   is($g, $e, $i);
}

1;


sed -e 's/\blong  *int\b/int/g' -e 's/\blong\b/int/g' -e 's/\bint\(  *\)int\b/long\1long/g'

Just replace those back that are now wrong?

edits: added white space conservation, added Kerrek SB's fix


If you are willing to do four passes, convert long int to long$int, convert long to int, then int int to long long, and long$int back to long int.


foreach my $line (@lines_in_the_file) {
    $line =~ s/\blong long\b/SOMETHINGFUNKY/g;
}

foreach my $line (@lines_in_the_file) {
    $line =~ s/\blong\b/int/g;
}

foreach my $line (@lines_in_the_file) {
    $line =~ s/SOMETHINGFUNKY/long long/g;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜