How to increment the last number in a string; bash












7















I have a string that looks something like
/foo/bar/baz59_ 5stuff.thing



I would like to increase the last number (5 in the example) by one, if it's greater than another variable. A 9 would be increased to 10. Note that the last number could be multiple digits also; also that "stuff.thing" could be anything; other than a number; so it can't be hard coded.



The above example would result in /foo/bar/baz59_ 6stuff.thing



I've found multiple questions (and answers) that would extract the last number from the string, and obviously that could then be used in a comparison.
The issue I'm having is how to ensure that when I do the replace, I only replace the last number (since obviously I can't just replace "5" for "6"). Can anyone make any suggestions?



awk/sed/bash/grep are all viable.










share|improve this question




















  • 1





    If the last number is 9, what's the desired outcome? What if it's 59?

    – James Brown
    2 days ago






  • 1





    if the last number is 9; then the desired is 10. 59; 60. 99->100 etc (question updated for posterity)

    – UKMonkey
    2 days ago













  • It's always preceded by an underscore this last number of yours?

    – gboffi
    2 days ago











  • @gboffi no; the previous character is not fixed.

    – UKMonkey
    2 days ago











  • if it's greater than a script argument you mean the whole string, or the number? if the number, do you mean increment the last number in the string that is greater than an argument, or increment the last number in the string if it is greater than an argument?

    – ysth
    2 days ago
















7















I have a string that looks something like
/foo/bar/baz59_ 5stuff.thing



I would like to increase the last number (5 in the example) by one, if it's greater than another variable. A 9 would be increased to 10. Note that the last number could be multiple digits also; also that "stuff.thing" could be anything; other than a number; so it can't be hard coded.



The above example would result in /foo/bar/baz59_ 6stuff.thing



I've found multiple questions (and answers) that would extract the last number from the string, and obviously that could then be used in a comparison.
The issue I'm having is how to ensure that when I do the replace, I only replace the last number (since obviously I can't just replace "5" for "6"). Can anyone make any suggestions?



awk/sed/bash/grep are all viable.










share|improve this question




















  • 1





    If the last number is 9, what's the desired outcome? What if it's 59?

    – James Brown
    2 days ago






  • 1





    if the last number is 9; then the desired is 10. 59; 60. 99->100 etc (question updated for posterity)

    – UKMonkey
    2 days ago













  • It's always preceded by an underscore this last number of yours?

    – gboffi
    2 days ago











  • @gboffi no; the previous character is not fixed.

    – UKMonkey
    2 days ago











  • if it's greater than a script argument you mean the whole string, or the number? if the number, do you mean increment the last number in the string that is greater than an argument, or increment the last number in the string if it is greater than an argument?

    – ysth
    2 days ago














7












7








7


1






I have a string that looks something like
/foo/bar/baz59_ 5stuff.thing



I would like to increase the last number (5 in the example) by one, if it's greater than another variable. A 9 would be increased to 10. Note that the last number could be multiple digits also; also that "stuff.thing" could be anything; other than a number; so it can't be hard coded.



The above example would result in /foo/bar/baz59_ 6stuff.thing



I've found multiple questions (and answers) that would extract the last number from the string, and obviously that could then be used in a comparison.
The issue I'm having is how to ensure that when I do the replace, I only replace the last number (since obviously I can't just replace "5" for "6"). Can anyone make any suggestions?



awk/sed/bash/grep are all viable.










share|improve this question
















I have a string that looks something like
/foo/bar/baz59_ 5stuff.thing



I would like to increase the last number (5 in the example) by one, if it's greater than another variable. A 9 would be increased to 10. Note that the last number could be multiple digits also; also that "stuff.thing" could be anything; other than a number; so it can't be hard coded.



The above example would result in /foo/bar/baz59_ 6stuff.thing



I've found multiple questions (and answers) that would extract the last number from the string, and obviously that could then be used in a comparison.
The issue I'm having is how to ensure that when I do the replace, I only replace the last number (since obviously I can't just replace "5" for "6"). Can anyone make any suggestions?



awk/sed/bash/grep are all viable.







bash perl awk sed






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 2 days ago







UKMonkey

















asked 2 days ago









UKMonkeyUKMonkey

5,68731227




5,68731227








  • 1





    If the last number is 9, what's the desired outcome? What if it's 59?

    – James Brown
    2 days ago






  • 1





    if the last number is 9; then the desired is 10. 59; 60. 99->100 etc (question updated for posterity)

    – UKMonkey
    2 days ago













  • It's always preceded by an underscore this last number of yours?

    – gboffi
    2 days ago











  • @gboffi no; the previous character is not fixed.

    – UKMonkey
    2 days ago











  • if it's greater than a script argument you mean the whole string, or the number? if the number, do you mean increment the last number in the string that is greater than an argument, or increment the last number in the string if it is greater than an argument?

    – ysth
    2 days ago














  • 1





    If the last number is 9, what's the desired outcome? What if it's 59?

    – James Brown
    2 days ago






  • 1





    if the last number is 9; then the desired is 10. 59; 60. 99->100 etc (question updated for posterity)

    – UKMonkey
    2 days ago













  • It's always preceded by an underscore this last number of yours?

    – gboffi
    2 days ago











  • @gboffi no; the previous character is not fixed.

    – UKMonkey
    2 days ago











  • if it's greater than a script argument you mean the whole string, or the number? if the number, do you mean increment the last number in the string that is greater than an argument, or increment the last number in the string if it is greater than an argument?

    – ysth
    2 days ago








1




1





If the last number is 9, what's the desired outcome? What if it's 59?

– James Brown
2 days ago





If the last number is 9, what's the desired outcome? What if it's 59?

– James Brown
2 days ago




1




1





if the last number is 9; then the desired is 10. 59; 60. 99->100 etc (question updated for posterity)

– UKMonkey
2 days ago







if the last number is 9; then the desired is 10. 59; 60. 99->100 etc (question updated for posterity)

– UKMonkey
2 days ago















It's always preceded by an underscore this last number of yours?

– gboffi
2 days ago





It's always preceded by an underscore this last number of yours?

– gboffi
2 days ago













@gboffi no; the previous character is not fixed.

– UKMonkey
2 days ago





@gboffi no; the previous character is not fixed.

– UKMonkey
2 days ago













if it's greater than a script argument you mean the whole string, or the number? if the number, do you mean increment the last number in the string that is greater than an argument, or increment the last number in the string if it is greater than an argument?

– ysth
2 days ago





if it's greater than a script argument you mean the whole string, or the number? if the number, do you mean increment the last number in the string that is greater than an argument, or increment the last number in the string if it is greater than an argument?

– ysth
2 days ago












6 Answers
6






active

oldest

votes


















7














Updated Answer



Thanks to @EdMorton for pointing out the further requirement of the number exceeding a threshold. That can be done like this:



perl -spe 's/(d+)(?!.*d+)/$1>$thresh? $1+1 : $1/e' <<<  "abc123_456.txt" -- -thresh=500


Original Answer



You can evaluate/calculate a replacement with /e in Perl regexes. Here I just add 1 to the captured string of digits but you can do more complicated stuff:



perl -pe 's/(d+)(?!.*d+)/$1+1/e' <<< "abc123_456.txt"
abc123_457.txt


The (?!.*d+) is (hopefully) a negative look-ahead for any more digits.



The $1 represents any sequence of digits captured in the capture group (d+).



Note that this would need modification to handle decimal numbers, negative numbers and scientific notation - but that is possible.






share|improve this answer


























  • This seems to work perfectly; and even handles a string containing quotes

    – UKMonkey
    2 days ago






  • 5





    or s/.*(?<!d)K(d+)/$1+1/sea

    – ysth
    2 days ago






  • 2





    @EdMorton Well spotted! I hadn't seen that, but have added it in now.

    – Mark Setchell
    2 days ago






  • 1





    or s/(d+)(?=D*$)/$1+1/ea

    – Miller
    2 days ago











  • Thank you all for your alternative suggestions.

    – Mark Setchell
    2 days ago



















4














Using bash regular expression matching:



$ f="/foo/bar/baz59_ 99stuff.thing"
$ [[ $f =~ ([0-9]+)([^0-9]+)$ ]]


OK, what do we have now?



$ declare -p BASH_REMATCH
declare -ar BASH_REMATCH=([0]="99stuff.thing" [1]="99" [2]="stuff.thing")


So we can construct the new filename



if [[ $f =~ ([0-9]+)([^0-9]+)$ ]]; then
prefix=${f%${BASH_REMATCH[0]}} # remove "99stuff.thing" from $f
number=$(( 10#${BASH_REMATCH[1]} + 1 )) # use "10#" to force base10
new=${prefix}${number}${BASH_REMATCH[2]}
echo $new
fi
# => /foo/bar/baz59_ 100stuff.thing





share|improve this answer

































    4














    With GNU awk for the 3rd arg to match():



    $ awk -v t=3 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
    /foo/bar/baz59_ 6stuff.thing


    Just set t to whatever your threshold value is for incrementing, e.g.:



    $ awk -v t=7 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
    /foo/bar/baz59_ 5stuff.thing





    share|improve this answer































      1















      if it's greater than a script argument.




      If I get it correctly(I am assuming you are passing an argument through a script and if its value is greater than string's 2nd field digit then increase 1 into that 2nd field's digit), could you please try following once.



      cat script.ksh
      value=$1
      echo "/foo/bar/baz59_ 5stuff.thing" |
      awk -v arg="$value" '
      match($2,/[0-9]+/){
      val=substr($2,RSTART,RLENGTH)
      val=val<arg?val+1:val
      $2=val substr($2,RSTART+RLENGTH)
      }
      1'


      Here is an example when I run script.ksh it gives following output.



      /script.ksh 7
      /foo/bar/baz59_ 6stuff.thing





      share|improve this answer


























      • @UKMonkey, could you please check this one also once and let me know if this works for you?

        – RavinderSingh13
        2 days ago






      • 1





        works fine! thanks

        – UKMonkey
        2 days ago













      • @UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)

        – RavinderSingh13
        2 days ago













      • it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.

        – UKMonkey
        2 days ago











      • @UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)

        – RavinderSingh13
        2 days ago





















      1














      Here is a shorter gnu awk approach:



      cat incr.awk
      {
      n = split($0, a, /[0-9]+/, b)
      for(i=1; i<n; i++)
      s = s a[i] b[i] + (b[i] < max && i == n-1 ? 1 : 0)
      print s a[i]
      }


      Then use it as:



      awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 5stuff.thing'
      /foo/bar/baz59_ 6stuff.thing

      awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 79stuff.thing'
      /foo/bar/baz59_ 80stuff.thing


      awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 90stuff.thing'
      /foo/bar/baz59_ 90stuff.thing

      awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 80stuff.thing'
      /foo/bar/baz59_ 80stuff.thing

      awk -v max=80 -f incr.awk <<< '/foo/bar/stuff.thing'
      /foo/bar/stuff.thing





      share|improve this answer































        1














        An awk:



        $ echo /foo/bar/baz59_ 99stuff.thing |
        awk '
        /[0-9]/ {
        rstart=1 # keep track of the start
        while(match(substr($0,rstart),/[0-9]+/)) { # while numbers last
        rstart+=RSTART+RLENGTH-1 # increase rstart
        rlength=RLENGTH # remember length too
        }
        v=substr($0,rstart-rlength,rlength)+1 # increase last number
        print substr($0,1,rstart-rlength-1) v substr($0,rstart) # print in parts
        next
        }1' # in case there was no number
        /foo/bar/baz59_ 100stuff.thing


        Edit:



        Whoops, I missed the argument requirement (increase the last number - - by a one, if it's greater than a script argument):



        $ echo /foo/bar/baz59_ 99stuff.thing |
        awk -v arg=100 '
        /[0-9]/ {
        rstart=1
        while(match(substr($0,rstart),/[0-9]+/)) {
        rstart+=RSTART+RLENGTH-1
        rlength=RLENGTH
        }
        v=substr($0,rstart-rlength,rlength)
        if(0+v>arg) { # test if v greater that argument
        print substr($0,1,rstart-rlength-1) v+1 substr($0,rstart)
        next
        }
        }1'


        Output now:



        /foo/bar/baz59_ 99stuff.thing





        share|improve this answer


























        • Updated with the script argument requirement. Missed it at first.

          – James Brown
          2 days ago











        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54367360%2fhow-to-increment-the-last-number-in-a-string-bash%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        6 Answers
        6






        active

        oldest

        votes








        6 Answers
        6






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        7














        Updated Answer



        Thanks to @EdMorton for pointing out the further requirement of the number exceeding a threshold. That can be done like this:



        perl -spe 's/(d+)(?!.*d+)/$1>$thresh? $1+1 : $1/e' <<<  "abc123_456.txt" -- -thresh=500


        Original Answer



        You can evaluate/calculate a replacement with /e in Perl regexes. Here I just add 1 to the captured string of digits but you can do more complicated stuff:



        perl -pe 's/(d+)(?!.*d+)/$1+1/e' <<< "abc123_456.txt"
        abc123_457.txt


        The (?!.*d+) is (hopefully) a negative look-ahead for any more digits.



        The $1 represents any sequence of digits captured in the capture group (d+).



        Note that this would need modification to handle decimal numbers, negative numbers and scientific notation - but that is possible.






        share|improve this answer


























        • This seems to work perfectly; and even handles a string containing quotes

          – UKMonkey
          2 days ago






        • 5





          or s/.*(?<!d)K(d+)/$1+1/sea

          – ysth
          2 days ago






        • 2





          @EdMorton Well spotted! I hadn't seen that, but have added it in now.

          – Mark Setchell
          2 days ago






        • 1





          or s/(d+)(?=D*$)/$1+1/ea

          – Miller
          2 days ago











        • Thank you all for your alternative suggestions.

          – Mark Setchell
          2 days ago
















        7














        Updated Answer



        Thanks to @EdMorton for pointing out the further requirement of the number exceeding a threshold. That can be done like this:



        perl -spe 's/(d+)(?!.*d+)/$1>$thresh? $1+1 : $1/e' <<<  "abc123_456.txt" -- -thresh=500


        Original Answer



        You can evaluate/calculate a replacement with /e in Perl regexes. Here I just add 1 to the captured string of digits but you can do more complicated stuff:



        perl -pe 's/(d+)(?!.*d+)/$1+1/e' <<< "abc123_456.txt"
        abc123_457.txt


        The (?!.*d+) is (hopefully) a negative look-ahead for any more digits.



        The $1 represents any sequence of digits captured in the capture group (d+).



        Note that this would need modification to handle decimal numbers, negative numbers and scientific notation - but that is possible.






        share|improve this answer


























        • This seems to work perfectly; and even handles a string containing quotes

          – UKMonkey
          2 days ago






        • 5





          or s/.*(?<!d)K(d+)/$1+1/sea

          – ysth
          2 days ago






        • 2





          @EdMorton Well spotted! I hadn't seen that, but have added it in now.

          – Mark Setchell
          2 days ago






        • 1





          or s/(d+)(?=D*$)/$1+1/ea

          – Miller
          2 days ago











        • Thank you all for your alternative suggestions.

          – Mark Setchell
          2 days ago














        7












        7








        7







        Updated Answer



        Thanks to @EdMorton for pointing out the further requirement of the number exceeding a threshold. That can be done like this:



        perl -spe 's/(d+)(?!.*d+)/$1>$thresh? $1+1 : $1/e' <<<  "abc123_456.txt" -- -thresh=500


        Original Answer



        You can evaluate/calculate a replacement with /e in Perl regexes. Here I just add 1 to the captured string of digits but you can do more complicated stuff:



        perl -pe 's/(d+)(?!.*d+)/$1+1/e' <<< "abc123_456.txt"
        abc123_457.txt


        The (?!.*d+) is (hopefully) a negative look-ahead for any more digits.



        The $1 represents any sequence of digits captured in the capture group (d+).



        Note that this would need modification to handle decimal numbers, negative numbers and scientific notation - but that is possible.






        share|improve this answer















        Updated Answer



        Thanks to @EdMorton for pointing out the further requirement of the number exceeding a threshold. That can be done like this:



        perl -spe 's/(d+)(?!.*d+)/$1>$thresh? $1+1 : $1/e' <<<  "abc123_456.txt" -- -thresh=500


        Original Answer



        You can evaluate/calculate a replacement with /e in Perl regexes. Here I just add 1 to the captured string of digits but you can do more complicated stuff:



        perl -pe 's/(d+)(?!.*d+)/$1+1/e' <<< "abc123_456.txt"
        abc123_457.txt


        The (?!.*d+) is (hopefully) a negative look-ahead for any more digits.



        The $1 represents any sequence of digits captured in the capture group (d+).



        Note that this would need modification to handle decimal numbers, negative numbers and scientific notation - but that is possible.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 2 days ago

























        answered 2 days ago









        Mark SetchellMark Setchell

        87.9k676176




        87.9k676176













        • This seems to work perfectly; and even handles a string containing quotes

          – UKMonkey
          2 days ago






        • 5





          or s/.*(?<!d)K(d+)/$1+1/sea

          – ysth
          2 days ago






        • 2





          @EdMorton Well spotted! I hadn't seen that, but have added it in now.

          – Mark Setchell
          2 days ago






        • 1





          or s/(d+)(?=D*$)/$1+1/ea

          – Miller
          2 days ago











        • Thank you all for your alternative suggestions.

          – Mark Setchell
          2 days ago



















        • This seems to work perfectly; and even handles a string containing quotes

          – UKMonkey
          2 days ago






        • 5





          or s/.*(?<!d)K(d+)/$1+1/sea

          – ysth
          2 days ago






        • 2





          @EdMorton Well spotted! I hadn't seen that, but have added it in now.

          – Mark Setchell
          2 days ago






        • 1





          or s/(d+)(?=D*$)/$1+1/ea

          – Miller
          2 days ago











        • Thank you all for your alternative suggestions.

          – Mark Setchell
          2 days ago

















        This seems to work perfectly; and even handles a string containing quotes

        – UKMonkey
        2 days ago





        This seems to work perfectly; and even handles a string containing quotes

        – UKMonkey
        2 days ago




        5




        5





        or s/.*(?<!d)K(d+)/$1+1/sea

        – ysth
        2 days ago





        or s/.*(?<!d)K(d+)/$1+1/sea

        – ysth
        2 days ago




        2




        2





        @EdMorton Well spotted! I hadn't seen that, but have added it in now.

        – Mark Setchell
        2 days ago





        @EdMorton Well spotted! I hadn't seen that, but have added it in now.

        – Mark Setchell
        2 days ago




        1




        1





        or s/(d+)(?=D*$)/$1+1/ea

        – Miller
        2 days ago





        or s/(d+)(?=D*$)/$1+1/ea

        – Miller
        2 days ago













        Thank you all for your alternative suggestions.

        – Mark Setchell
        2 days ago





        Thank you all for your alternative suggestions.

        – Mark Setchell
        2 days ago













        4














        Using bash regular expression matching:



        $ f="/foo/bar/baz59_ 99stuff.thing"
        $ [[ $f =~ ([0-9]+)([^0-9]+)$ ]]


        OK, what do we have now?



        $ declare -p BASH_REMATCH
        declare -ar BASH_REMATCH=([0]="99stuff.thing" [1]="99" [2]="stuff.thing")


        So we can construct the new filename



        if [[ $f =~ ([0-9]+)([^0-9]+)$ ]]; then
        prefix=${f%${BASH_REMATCH[0]}} # remove "99stuff.thing" from $f
        number=$(( 10#${BASH_REMATCH[1]} + 1 )) # use "10#" to force base10
        new=${prefix}${number}${BASH_REMATCH[2]}
        echo $new
        fi
        # => /foo/bar/baz59_ 100stuff.thing





        share|improve this answer






























          4














          Using bash regular expression matching:



          $ f="/foo/bar/baz59_ 99stuff.thing"
          $ [[ $f =~ ([0-9]+)([^0-9]+)$ ]]


          OK, what do we have now?



          $ declare -p BASH_REMATCH
          declare -ar BASH_REMATCH=([0]="99stuff.thing" [1]="99" [2]="stuff.thing")


          So we can construct the new filename



          if [[ $f =~ ([0-9]+)([^0-9]+)$ ]]; then
          prefix=${f%${BASH_REMATCH[0]}} # remove "99stuff.thing" from $f
          number=$(( 10#${BASH_REMATCH[1]} + 1 )) # use "10#" to force base10
          new=${prefix}${number}${BASH_REMATCH[2]}
          echo $new
          fi
          # => /foo/bar/baz59_ 100stuff.thing





          share|improve this answer




























            4












            4








            4







            Using bash regular expression matching:



            $ f="/foo/bar/baz59_ 99stuff.thing"
            $ [[ $f =~ ([0-9]+)([^0-9]+)$ ]]


            OK, what do we have now?



            $ declare -p BASH_REMATCH
            declare -ar BASH_REMATCH=([0]="99stuff.thing" [1]="99" [2]="stuff.thing")


            So we can construct the new filename



            if [[ $f =~ ([0-9]+)([^0-9]+)$ ]]; then
            prefix=${f%${BASH_REMATCH[0]}} # remove "99stuff.thing" from $f
            number=$(( 10#${BASH_REMATCH[1]} + 1 )) # use "10#" to force base10
            new=${prefix}${number}${BASH_REMATCH[2]}
            echo $new
            fi
            # => /foo/bar/baz59_ 100stuff.thing





            share|improve this answer















            Using bash regular expression matching:



            $ f="/foo/bar/baz59_ 99stuff.thing"
            $ [[ $f =~ ([0-9]+)([^0-9]+)$ ]]


            OK, what do we have now?



            $ declare -p BASH_REMATCH
            declare -ar BASH_REMATCH=([0]="99stuff.thing" [1]="99" [2]="stuff.thing")


            So we can construct the new filename



            if [[ $f =~ ([0-9]+)([^0-9]+)$ ]]; then
            prefix=${f%${BASH_REMATCH[0]}} # remove "99stuff.thing" from $f
            number=$(( 10#${BASH_REMATCH[1]} + 1 )) # use "10#" to force base10
            new=${prefix}${number}${BASH_REMATCH[2]}
            echo $new
            fi
            # => /foo/bar/baz59_ 100stuff.thing






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 2 days ago

























            answered 2 days ago









            glenn jackmanglenn jackman

            166k26144237




            166k26144237























                4














                With GNU awk for the 3rd arg to match():



                $ awk -v t=3 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
                /foo/bar/baz59_ 6stuff.thing


                Just set t to whatever your threshold value is for incrementing, e.g.:



                $ awk -v t=7 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
                /foo/bar/baz59_ 5stuff.thing





                share|improve this answer




























                  4














                  With GNU awk for the 3rd arg to match():



                  $ awk -v t=3 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
                  /foo/bar/baz59_ 6stuff.thing


                  Just set t to whatever your threshold value is for incrementing, e.g.:



                  $ awk -v t=7 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
                  /foo/bar/baz59_ 5stuff.thing





                  share|improve this answer


























                    4












                    4








                    4







                    With GNU awk for the 3rd arg to match():



                    $ awk -v t=3 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
                    /foo/bar/baz59_ 6stuff.thing


                    Just set t to whatever your threshold value is for incrementing, e.g.:



                    $ awk -v t=7 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
                    /foo/bar/baz59_ 5stuff.thing





                    share|improve this answer













                    With GNU awk for the 3rd arg to match():



                    $ awk -v t=3 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
                    /foo/bar/baz59_ 6stuff.thing


                    Just set t to whatever your threshold value is for incrementing, e.g.:



                    $ awk -v t=7 'match($0,/(.*)([0-9]+)([^0-9]*)$/,a) && a[2]>t{a[2]++; $0=a[1] a[2] a[3]} 1' file
                    /foo/bar/baz59_ 5stuff.thing






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered 2 days ago









                    Ed MortonEd Morton

                    109k124598




                    109k124598























                        1















                        if it's greater than a script argument.




                        If I get it correctly(I am assuming you are passing an argument through a script and if its value is greater than string's 2nd field digit then increase 1 into that 2nd field's digit), could you please try following once.



                        cat script.ksh
                        value=$1
                        echo "/foo/bar/baz59_ 5stuff.thing" |
                        awk -v arg="$value" '
                        match($2,/[0-9]+/){
                        val=substr($2,RSTART,RLENGTH)
                        val=val<arg?val+1:val
                        $2=val substr($2,RSTART+RLENGTH)
                        }
                        1'


                        Here is an example when I run script.ksh it gives following output.



                        /script.ksh 7
                        /foo/bar/baz59_ 6stuff.thing





                        share|improve this answer


























                        • @UKMonkey, could you please check this one also once and let me know if this works for you?

                          – RavinderSingh13
                          2 days ago






                        • 1





                          works fine! thanks

                          – UKMonkey
                          2 days ago













                        • @UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)

                          – RavinderSingh13
                          2 days ago













                        • it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.

                          – UKMonkey
                          2 days ago











                        • @UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)

                          – RavinderSingh13
                          2 days ago


















                        1















                        if it's greater than a script argument.




                        If I get it correctly(I am assuming you are passing an argument through a script and if its value is greater than string's 2nd field digit then increase 1 into that 2nd field's digit), could you please try following once.



                        cat script.ksh
                        value=$1
                        echo "/foo/bar/baz59_ 5stuff.thing" |
                        awk -v arg="$value" '
                        match($2,/[0-9]+/){
                        val=substr($2,RSTART,RLENGTH)
                        val=val<arg?val+1:val
                        $2=val substr($2,RSTART+RLENGTH)
                        }
                        1'


                        Here is an example when I run script.ksh it gives following output.



                        /script.ksh 7
                        /foo/bar/baz59_ 6stuff.thing





                        share|improve this answer


























                        • @UKMonkey, could you please check this one also once and let me know if this works for you?

                          – RavinderSingh13
                          2 days ago






                        • 1





                          works fine! thanks

                          – UKMonkey
                          2 days ago













                        • @UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)

                          – RavinderSingh13
                          2 days ago













                        • it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.

                          – UKMonkey
                          2 days ago











                        • @UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)

                          – RavinderSingh13
                          2 days ago
















                        1












                        1








                        1








                        if it's greater than a script argument.




                        If I get it correctly(I am assuming you are passing an argument through a script and if its value is greater than string's 2nd field digit then increase 1 into that 2nd field's digit), could you please try following once.



                        cat script.ksh
                        value=$1
                        echo "/foo/bar/baz59_ 5stuff.thing" |
                        awk -v arg="$value" '
                        match($2,/[0-9]+/){
                        val=substr($2,RSTART,RLENGTH)
                        val=val<arg?val+1:val
                        $2=val substr($2,RSTART+RLENGTH)
                        }
                        1'


                        Here is an example when I run script.ksh it gives following output.



                        /script.ksh 7
                        /foo/bar/baz59_ 6stuff.thing





                        share|improve this answer
















                        if it's greater than a script argument.




                        If I get it correctly(I am assuming you are passing an argument through a script and if its value is greater than string's 2nd field digit then increase 1 into that 2nd field's digit), could you please try following once.



                        cat script.ksh
                        value=$1
                        echo "/foo/bar/baz59_ 5stuff.thing" |
                        awk -v arg="$value" '
                        match($2,/[0-9]+/){
                        val=substr($2,RSTART,RLENGTH)
                        val=val<arg?val+1:val
                        $2=val substr($2,RSTART+RLENGTH)
                        }
                        1'


                        Here is an example when I run script.ksh it gives following output.



                        /script.ksh 7
                        /foo/bar/baz59_ 6stuff.thing






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited 2 days ago

























                        answered 2 days ago









                        RavinderSingh13RavinderSingh13

                        26.9k41438




                        26.9k41438













                        • @UKMonkey, could you please check this one also once and let me know if this works for you?

                          – RavinderSingh13
                          2 days ago






                        • 1





                          works fine! thanks

                          – UKMonkey
                          2 days ago













                        • @UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)

                          – RavinderSingh13
                          2 days ago













                        • it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.

                          – UKMonkey
                          2 days ago











                        • @UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)

                          – RavinderSingh13
                          2 days ago





















                        • @UKMonkey, could you please check this one also once and let me know if this works for you?

                          – RavinderSingh13
                          2 days ago






                        • 1





                          works fine! thanks

                          – UKMonkey
                          2 days ago













                        • @UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)

                          – RavinderSingh13
                          2 days ago













                        • it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.

                          – UKMonkey
                          2 days ago











                        • @UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)

                          – RavinderSingh13
                          2 days ago



















                        @UKMonkey, could you please check this one also once and let me know if this works for you?

                        – RavinderSingh13
                        2 days ago





                        @UKMonkey, could you please check this one also once and let me know if this works for you?

                        – RavinderSingh13
                        2 days ago




                        1




                        1





                        works fine! thanks

                        – UKMonkey
                        2 days ago







                        works fine! thanks

                        – UKMonkey
                        2 days ago















                        @UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)

                        – RavinderSingh13
                        2 days ago







                        @UKMonkey, cool glad that it helped you, why I have specifically asked is no other solution have taken argument from script and compared it, so I wanted to make sure I understood question correctly, if you tested by passing argument then cool :)

                        – RavinderSingh13
                        2 days ago















                        it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.

                        – UKMonkey
                        2 days ago





                        it was the principle behind the replacement that I cared about - the full implementation such as how to plug in the string etc is a worry I didn't want to infect the question with.

                        – UKMonkey
                        2 days ago













                        @UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)

                        – RavinderSingh13
                        2 days ago







                        @UKMonkey, well(if I get it correctly) if that is complete requirement then you need not to worry now, you have complete solution now :)

                        – RavinderSingh13
                        2 days ago













                        1














                        Here is a shorter gnu awk approach:



                        cat incr.awk
                        {
                        n = split($0, a, /[0-9]+/, b)
                        for(i=1; i<n; i++)
                        s = s a[i] b[i] + (b[i] < max && i == n-1 ? 1 : 0)
                        print s a[i]
                        }


                        Then use it as:



                        awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 5stuff.thing'
                        /foo/bar/baz59_ 6stuff.thing

                        awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 79stuff.thing'
                        /foo/bar/baz59_ 80stuff.thing


                        awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 90stuff.thing'
                        /foo/bar/baz59_ 90stuff.thing

                        awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 80stuff.thing'
                        /foo/bar/baz59_ 80stuff.thing

                        awk -v max=80 -f incr.awk <<< '/foo/bar/stuff.thing'
                        /foo/bar/stuff.thing





                        share|improve this answer




























                          1














                          Here is a shorter gnu awk approach:



                          cat incr.awk
                          {
                          n = split($0, a, /[0-9]+/, b)
                          for(i=1; i<n; i++)
                          s = s a[i] b[i] + (b[i] < max && i == n-1 ? 1 : 0)
                          print s a[i]
                          }


                          Then use it as:



                          awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 5stuff.thing'
                          /foo/bar/baz59_ 6stuff.thing

                          awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 79stuff.thing'
                          /foo/bar/baz59_ 80stuff.thing


                          awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 90stuff.thing'
                          /foo/bar/baz59_ 90stuff.thing

                          awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 80stuff.thing'
                          /foo/bar/baz59_ 80stuff.thing

                          awk -v max=80 -f incr.awk <<< '/foo/bar/stuff.thing'
                          /foo/bar/stuff.thing





                          share|improve this answer


























                            1












                            1








                            1







                            Here is a shorter gnu awk approach:



                            cat incr.awk
                            {
                            n = split($0, a, /[0-9]+/, b)
                            for(i=1; i<n; i++)
                            s = s a[i] b[i] + (b[i] < max && i == n-1 ? 1 : 0)
                            print s a[i]
                            }


                            Then use it as:



                            awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 5stuff.thing'
                            /foo/bar/baz59_ 6stuff.thing

                            awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 79stuff.thing'
                            /foo/bar/baz59_ 80stuff.thing


                            awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 90stuff.thing'
                            /foo/bar/baz59_ 90stuff.thing

                            awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 80stuff.thing'
                            /foo/bar/baz59_ 80stuff.thing

                            awk -v max=80 -f incr.awk <<< '/foo/bar/stuff.thing'
                            /foo/bar/stuff.thing





                            share|improve this answer













                            Here is a shorter gnu awk approach:



                            cat incr.awk
                            {
                            n = split($0, a, /[0-9]+/, b)
                            for(i=1; i<n; i++)
                            s = s a[i] b[i] + (b[i] < max && i == n-1 ? 1 : 0)
                            print s a[i]
                            }


                            Then use it as:



                            awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 5stuff.thing'
                            /foo/bar/baz59_ 6stuff.thing

                            awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 79stuff.thing'
                            /foo/bar/baz59_ 80stuff.thing


                            awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 90stuff.thing'
                            /foo/bar/baz59_ 90stuff.thing

                            awk -v max=80 -f incr.awk <<< '/foo/bar/baz59_ 80stuff.thing'
                            /foo/bar/baz59_ 80stuff.thing

                            awk -v max=80 -f incr.awk <<< '/foo/bar/stuff.thing'
                            /foo/bar/stuff.thing






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered 2 days ago









                            anubhavaanubhava

                            524k46320395




                            524k46320395























                                1














                                An awk:



                                $ echo /foo/bar/baz59_ 99stuff.thing |
                                awk '
                                /[0-9]/ {
                                rstart=1 # keep track of the start
                                while(match(substr($0,rstart),/[0-9]+/)) { # while numbers last
                                rstart+=RSTART+RLENGTH-1 # increase rstart
                                rlength=RLENGTH # remember length too
                                }
                                v=substr($0,rstart-rlength,rlength)+1 # increase last number
                                print substr($0,1,rstart-rlength-1) v substr($0,rstart) # print in parts
                                next
                                }1' # in case there was no number
                                /foo/bar/baz59_ 100stuff.thing


                                Edit:



                                Whoops, I missed the argument requirement (increase the last number - - by a one, if it's greater than a script argument):



                                $ echo /foo/bar/baz59_ 99stuff.thing |
                                awk -v arg=100 '
                                /[0-9]/ {
                                rstart=1
                                while(match(substr($0,rstart),/[0-9]+/)) {
                                rstart+=RSTART+RLENGTH-1
                                rlength=RLENGTH
                                }
                                v=substr($0,rstart-rlength,rlength)
                                if(0+v>arg) { # test if v greater that argument
                                print substr($0,1,rstart-rlength-1) v+1 substr($0,rstart)
                                next
                                }
                                }1'


                                Output now:



                                /foo/bar/baz59_ 99stuff.thing





                                share|improve this answer


























                                • Updated with the script argument requirement. Missed it at first.

                                  – James Brown
                                  2 days ago
















                                1














                                An awk:



                                $ echo /foo/bar/baz59_ 99stuff.thing |
                                awk '
                                /[0-9]/ {
                                rstart=1 # keep track of the start
                                while(match(substr($0,rstart),/[0-9]+/)) { # while numbers last
                                rstart+=RSTART+RLENGTH-1 # increase rstart
                                rlength=RLENGTH # remember length too
                                }
                                v=substr($0,rstart-rlength,rlength)+1 # increase last number
                                print substr($0,1,rstart-rlength-1) v substr($0,rstart) # print in parts
                                next
                                }1' # in case there was no number
                                /foo/bar/baz59_ 100stuff.thing


                                Edit:



                                Whoops, I missed the argument requirement (increase the last number - - by a one, if it's greater than a script argument):



                                $ echo /foo/bar/baz59_ 99stuff.thing |
                                awk -v arg=100 '
                                /[0-9]/ {
                                rstart=1
                                while(match(substr($0,rstart),/[0-9]+/)) {
                                rstart+=RSTART+RLENGTH-1
                                rlength=RLENGTH
                                }
                                v=substr($0,rstart-rlength,rlength)
                                if(0+v>arg) { # test if v greater that argument
                                print substr($0,1,rstart-rlength-1) v+1 substr($0,rstart)
                                next
                                }
                                }1'


                                Output now:



                                /foo/bar/baz59_ 99stuff.thing





                                share|improve this answer


























                                • Updated with the script argument requirement. Missed it at first.

                                  – James Brown
                                  2 days ago














                                1












                                1








                                1







                                An awk:



                                $ echo /foo/bar/baz59_ 99stuff.thing |
                                awk '
                                /[0-9]/ {
                                rstart=1 # keep track of the start
                                while(match(substr($0,rstart),/[0-9]+/)) { # while numbers last
                                rstart+=RSTART+RLENGTH-1 # increase rstart
                                rlength=RLENGTH # remember length too
                                }
                                v=substr($0,rstart-rlength,rlength)+1 # increase last number
                                print substr($0,1,rstart-rlength-1) v substr($0,rstart) # print in parts
                                next
                                }1' # in case there was no number
                                /foo/bar/baz59_ 100stuff.thing


                                Edit:



                                Whoops, I missed the argument requirement (increase the last number - - by a one, if it's greater than a script argument):



                                $ echo /foo/bar/baz59_ 99stuff.thing |
                                awk -v arg=100 '
                                /[0-9]/ {
                                rstart=1
                                while(match(substr($0,rstart),/[0-9]+/)) {
                                rstart+=RSTART+RLENGTH-1
                                rlength=RLENGTH
                                }
                                v=substr($0,rstart-rlength,rlength)
                                if(0+v>arg) { # test if v greater that argument
                                print substr($0,1,rstart-rlength-1) v+1 substr($0,rstart)
                                next
                                }
                                }1'


                                Output now:



                                /foo/bar/baz59_ 99stuff.thing





                                share|improve this answer















                                An awk:



                                $ echo /foo/bar/baz59_ 99stuff.thing |
                                awk '
                                /[0-9]/ {
                                rstart=1 # keep track of the start
                                while(match(substr($0,rstart),/[0-9]+/)) { # while numbers last
                                rstart+=RSTART+RLENGTH-1 # increase rstart
                                rlength=RLENGTH # remember length too
                                }
                                v=substr($0,rstart-rlength,rlength)+1 # increase last number
                                print substr($0,1,rstart-rlength-1) v substr($0,rstart) # print in parts
                                next
                                }1' # in case there was no number
                                /foo/bar/baz59_ 100stuff.thing


                                Edit:



                                Whoops, I missed the argument requirement (increase the last number - - by a one, if it's greater than a script argument):



                                $ echo /foo/bar/baz59_ 99stuff.thing |
                                awk -v arg=100 '
                                /[0-9]/ {
                                rstart=1
                                while(match(substr($0,rstart),/[0-9]+/)) {
                                rstart+=RSTART+RLENGTH-1
                                rlength=RLENGTH
                                }
                                v=substr($0,rstart-rlength,rlength)
                                if(0+v>arg) { # test if v greater that argument
                                print substr($0,1,rstart-rlength-1) v+1 substr($0,rstart)
                                next
                                }
                                }1'


                                Output now:



                                /foo/bar/baz59_ 99stuff.thing






                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited 2 days ago

























                                answered 2 days ago









                                James BrownJames Brown

                                18.4k31635




                                18.4k31635













                                • Updated with the script argument requirement. Missed it at first.

                                  – James Brown
                                  2 days ago



















                                • Updated with the script argument requirement. Missed it at first.

                                  – James Brown
                                  2 days ago

















                                Updated with the script argument requirement. Missed it at first.

                                – James Brown
                                2 days ago





                                Updated with the script argument requirement. Missed it at first.

                                – James Brown
                                2 days ago


















                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54367360%2fhow-to-increment-the-last-number-in-a-string-bash%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                Paul Cézanne

                                UIScrollView CustomStickyHeader Resize height generates problems when scroll is too fast

                                Angular material date-picker (MatDatepicker) auto completes the date on focus out