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

Let's say I have a line with an undefined number of numbers in it, seperated by random text but surrounded by spaces. Something like this will do for an example:

/dev/hda5               303344     99042    188641  35% /

Basically, I want to take anything that matches this: m/ (\d+) /

...and do something to it (ie divide by 1024), then stick it back in where it was. It would be nice to be able to do this with perl -pe 'something', but I can't even figure out how to do it at all - how do I match once on a line, change something, then start matching again after the spot I changed on the same line?

For example, let's assume I wanted to take every big number i see in my input and turn it into that number divided by 1000. How do I do that?

Replies are listed 'Best First'.
Re: One-liner (or few-liner) for massaging regexps?
by japhy (Canon) on Sep 17, 2002 at 18:03 UTC
    perl -pe 's{ (\d+) }{sprintf " %g ", $1/1000}'

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: One-liner (or few-liner) for massaging regexps?
by RMGir (Prior) on Sep 17, 2002 at 17:50 UTC
    use df -m to get megabytes? :)

    Oh, you mean in perl...

    perl -pe's{(\d+)}{($1>1024)?(int($1/1024)):$1}eg;'
    The only problem with this is that what you replace isn't going to be the same width as what you removed, which could mess up columns.
    perl -pe's{(\d+)}{($1>1024)?(sprintf("%".length($1)."d",$1/1024)):$1}e +g;'

    --
    Mike
      That variable sprintf can be easier written as perl -pe's{\b(\d+)\b}{ sprintf "%*d", length $1, $1/1024 }ge' Update: added \bs - thanks to sauoq.

      Makeshifts last the longest.

Re: One-liner (or few-liner) for massaging regexps?
by sauoq (Abbot) on Sep 17, 2002 at 17:44 UTC
    perl -pe 's! (\d+)!" ".$1/1024!eg'

    Update: perl -pe 's!\b(\d+)(\s)!($1/1024).$2!eg' would be better.

    -sauoq
    "My two cents aren't worth a dime.";
    
Re: One-liner (or few-liner) for massaging regexps?
by Aristotle (Chancellor) on Sep 18, 2002 at 07:05 UTC
    sauoq just /msg'd me to point out that all the regexes here are broken: they will happily replace the 5 in /dev/hda5 along with all the other numbers. It has to be \b(\d+)\b to work correctly.

    Makeshifts last the longest.

      I did but I was wrong. I think japhy's is actually fine as long as the those are real spaces in the original and not tabs. I think most df commands do use spaces and mine relied on the same thing. Unfortunately, two \bs won't work either. They break on the disk utilization percentage. My original reply breaks on it too because I don't match a space after the number. Matching either a \b or a \s before the number and a \s after it would work.

      -sauoq
      "My two cents aren't worth a dime.";