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

I was asked to solve a problem at work so I tried to make it as short possible.

Problem:

Read and Modify a file in place containing lines in the format of "variable = number" taking into consideration any whitespace around the equal sign.

Example input:

one=1 two=2 three=3 xyz=20

Increment the value of a specific variable in the file and write it back out.

Ex: where variable is xyz.

one=1 two=2 three=3 xyz=21

My attempt:

where xyz is the variable whose value is being incremented by 1 and test.data is the file containing data.

perl -p -i.bak -e 's/$1/$a/ if ((/xyz\s*=\s*([0-9]*)\s*/)&&($a=$1+1))' + test.data
-mlm

Replies are listed 'Best First'.
Re: Can anyone make this shorter?
by CheeseLord (Deacon) on Aug 21, 2001 at 19:45 UTC

    Arr... Cheesy likes golfing...

    #23456789_123456789_123456789_123456789_12345678 (48) perl -pi.bak -e's/(xyz\s*=\s*)(\d+)/$1.($2+1)/e' test.data

    Update: Anything maverick can do, I can do better... (j/k):

    perl -pi.bak -e'/^xyz\b/&&s/\d+$/$&+1/e' (40)

    As long as your file is formatted correctly, that should avoid any trip-ups.

    And a slice of -pie: Check out perlrun for all your command-line option needs. :-)

    His Royal Cheeziness

      Excuse me whilst I bow and kiss your cycle clips. I would really love to know how that line does what it does. I get the regex stuff, but it's the perl -pi.bak -e ..... test.data bit I have no clue about. Would any monk be kind enough to enlighten me?

      § George Sherston
Re: Can anyone make this shorter?
by maverick (Curate) on Aug 21, 2001 at 19:50 UTC
    #!/usr/bin/perl -p -i # s/(xyz\s*=\s*)(\d+)/$1.($2+1)/e; /xyz/?s/(\d+)/$1+1/e:1;
    Updated:CheeseLord beat me to it.
    Update 2: Found a shorter one

    /\/\averick
    perl -l -e "eval pack('h*','072796e6470272f2c5f2c5166756279636b672');"

Re: Can anyone make this shorter?
by japhy (Canon) on Aug 21, 2001 at 22:08 UTC
    # 3456789_123456789_123456789_123456789_1 perl -pi.bak -e'/^xyz\s*=/&&s/\d+/1+$&/e'

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

      When I read the original article, it didn't seem that making a backup was part of the spec? Therefore:
      # 3456789_123456789_123456789_1234567 perl -pi -e'/^xyz\s*=/&&s/\d+/1+$&/e'
Re: Can anyone make this shorter?
by kschwab (Vicar) on Aug 21, 2001 at 19:56 UTC
    If I understand the question right...
    perl -pi.bak -e 's/(xyz\s*=\s*)(\d*)/$1.($2+1)/e' test.data
    Update: bah, I should type faster :)
Re: Can anyone make this shorter?
by MZSanford (Curate) on Aug 21, 2001 at 19:52 UTC
    Untested, but i thikng ... perl -p -i.bak -e 's/(\d+)$/$1+1/e if (/^xyz\s*=/)'
    Update : oops, misread question, changed (yet, still untested)
    can't sleep clowns will eat me
    -- MZSanford
      Interesting, but it will not change a specific variable in the file. -mlm