Bash string replace function similar to Javascript String.prototype.replace()










4















In JS, I can use a function String.prototype.replace() when replacing a submatch in a regular expression. For example:



var x = 'a1b2c3'.replace(/(d+)/g, (num) => 
return num*num+1
)
console.log(x)
// 'a2b5c10'


I've tried using sed but it seems that invoking an operator $(()) inside of the replacement is not possible.



$ echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/1$((2*2+1))3/g'
# Output: a$((1*1+1))b$((2*2+1))c$((3*3+1))


Is there a similar tool or function in bash that has the functionality similar to JS's String.replace()?










share|improve this question




























    4















    In JS, I can use a function String.prototype.replace() when replacing a submatch in a regular expression. For example:



    var x = 'a1b2c3'.replace(/(d+)/g, (num) => 
    return num*num+1
    )
    console.log(x)
    // 'a2b5c10'


    I've tried using sed but it seems that invoking an operator $(()) inside of the replacement is not possible.



    $ echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/1$((2*2+1))3/g'
    # Output: a$((1*1+1))b$((2*2+1))c$((3*3+1))


    Is there a similar tool or function in bash that has the functionality similar to JS's String.replace()?










    share|improve this question


























      4












      4








      4








      In JS, I can use a function String.prototype.replace() when replacing a submatch in a regular expression. For example:



      var x = 'a1b2c3'.replace(/(d+)/g, (num) => 
      return num*num+1
      )
      console.log(x)
      // 'a2b5c10'


      I've tried using sed but it seems that invoking an operator $(()) inside of the replacement is not possible.



      $ echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/1$((2*2+1))3/g'
      # Output: a$((1*1+1))b$((2*2+1))c$((3*3+1))


      Is there a similar tool or function in bash that has the functionality similar to JS's String.replace()?










      share|improve this question
















      In JS, I can use a function String.prototype.replace() when replacing a submatch in a regular expression. For example:



      var x = 'a1b2c3'.replace(/(d+)/g, (num) => 
      return num*num+1
      )
      console.log(x)
      // 'a2b5c10'


      I've tried using sed but it seems that invoking an operator $(()) inside of the replacement is not possible.



      $ echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/1$((2*2+1))3/g'
      # Output: a$((1*1+1))b$((2*2+1))c$((3*3+1))


      Is there a similar tool or function in bash that has the functionality similar to JS's String.replace()?







      javascript bash sed sh






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 11 '18 at 10:09







      Stanley Semilla

















      asked Nov 11 '18 at 10:06









      Stanley SemillaStanley Semilla

      354




      354






















          3 Answers
          3






          active

          oldest

          votes


















          1














          The bash shell does support a native regex operator which you can enable with the ~ flag. All you need to do is define a regex, take the captured groups and replace them with the modified values



          str='a1b2c3'
          re='^.*([0-9]+).*([0-9]+).*([0-9]+).*$'
          if [[ $str =~ $re ]]; then
          for match in "$BASH_REMATCH[@]"; do
          final="$str/$match/$((match*match+1))"
          done
          fi
          printf '%sn' "$final"


          The [[ $str =~ $re ]] does the regex match and updates the captured group array $BASH_REMATCH[@]. So for each of the element in the order of their appearance, we do the string substitution operator $str/old/new. The replacement value in your case is the number multiplied with itself and added by 1.



          Add more capturing groups to the regex .*([0-9]+) for subsequent matches.




          If not for a pure bash solution above, using an external utility like perl, one could do it as



          perl -pe 's/d+/$&*$&+1/ge' <<<"$str"


          The $& refers to the captured digit in the string and the e flag allows do arithmetic operations over the captured groups.






          share|improve this answer
































            1














            You can implement this in gawk using match() and substr().



            echo "a1b2c3" | awk '
            head = ""
            tail = $0

            while (match(tail, /[0-9]+/))
            num = substr(tail, RSTART, RLENGTH)
            num = num * num + 1
            head = head substr(tail, 1, RSTART-1) num
            tail = substr(tail, RSTART + RLENGTH)


            print head tail
            '


            Output



            a2b5c10





            share|improve this answer
































              0














              I am not sure this is my favorite answer, but just to let you know GNU sed does have external command capabilities:



              echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/echo 1$((2*2+1))3/ge' | sed 's/echo //g'


              e is the trick to pass the result externally.



              The most annoying thing - echo is appended when the g and e flags are combined to the substitution groups following the first one, so the second sed gets rid of them. If someone knows if there is something built in that would be great.



              Unfortunately



              echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/1$((2*2+1))3/ge'


              will get a working substitution but throw an error as a2b3c4 is not a command.






              share|improve this answer






















                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%2f53247642%2fbash-string-replace-function-similar-to-javascript-string-prototype-replace%23new-answer', 'question_page');

                );

                Post as a guest















                Required, but never shown

























                3 Answers
                3






                active

                oldest

                votes








                3 Answers
                3






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes









                1














                The bash shell does support a native regex operator which you can enable with the ~ flag. All you need to do is define a regex, take the captured groups and replace them with the modified values



                str='a1b2c3'
                re='^.*([0-9]+).*([0-9]+).*([0-9]+).*$'
                if [[ $str =~ $re ]]; then
                for match in "$BASH_REMATCH[@]"; do
                final="$str/$match/$((match*match+1))"
                done
                fi
                printf '%sn' "$final"


                The [[ $str =~ $re ]] does the regex match and updates the captured group array $BASH_REMATCH[@]. So for each of the element in the order of their appearance, we do the string substitution operator $str/old/new. The replacement value in your case is the number multiplied with itself and added by 1.



                Add more capturing groups to the regex .*([0-9]+) for subsequent matches.




                If not for a pure bash solution above, using an external utility like perl, one could do it as



                perl -pe 's/d+/$&*$&+1/ge' <<<"$str"


                The $& refers to the captured digit in the string and the e flag allows do arithmetic operations over the captured groups.






                share|improve this answer





























                  1














                  The bash shell does support a native regex operator which you can enable with the ~ flag. All you need to do is define a regex, take the captured groups and replace them with the modified values



                  str='a1b2c3'
                  re='^.*([0-9]+).*([0-9]+).*([0-9]+).*$'
                  if [[ $str =~ $re ]]; then
                  for match in "$BASH_REMATCH[@]"; do
                  final="$str/$match/$((match*match+1))"
                  done
                  fi
                  printf '%sn' "$final"


                  The [[ $str =~ $re ]] does the regex match and updates the captured group array $BASH_REMATCH[@]. So for each of the element in the order of their appearance, we do the string substitution operator $str/old/new. The replacement value in your case is the number multiplied with itself and added by 1.



                  Add more capturing groups to the regex .*([0-9]+) for subsequent matches.




                  If not for a pure bash solution above, using an external utility like perl, one could do it as



                  perl -pe 's/d+/$&*$&+1/ge' <<<"$str"


                  The $& refers to the captured digit in the string and the e flag allows do arithmetic operations over the captured groups.






                  share|improve this answer



























                    1












                    1








                    1







                    The bash shell does support a native regex operator which you can enable with the ~ flag. All you need to do is define a regex, take the captured groups and replace them with the modified values



                    str='a1b2c3'
                    re='^.*([0-9]+).*([0-9]+).*([0-9]+).*$'
                    if [[ $str =~ $re ]]; then
                    for match in "$BASH_REMATCH[@]"; do
                    final="$str/$match/$((match*match+1))"
                    done
                    fi
                    printf '%sn' "$final"


                    The [[ $str =~ $re ]] does the regex match and updates the captured group array $BASH_REMATCH[@]. So for each of the element in the order of their appearance, we do the string substitution operator $str/old/new. The replacement value in your case is the number multiplied with itself and added by 1.



                    Add more capturing groups to the regex .*([0-9]+) for subsequent matches.




                    If not for a pure bash solution above, using an external utility like perl, one could do it as



                    perl -pe 's/d+/$&*$&+1/ge' <<<"$str"


                    The $& refers to the captured digit in the string and the e flag allows do arithmetic operations over the captured groups.






                    share|improve this answer















                    The bash shell does support a native regex operator which you can enable with the ~ flag. All you need to do is define a regex, take the captured groups and replace them with the modified values



                    str='a1b2c3'
                    re='^.*([0-9]+).*([0-9]+).*([0-9]+).*$'
                    if [[ $str =~ $re ]]; then
                    for match in "$BASH_REMATCH[@]"; do
                    final="$str/$match/$((match*match+1))"
                    done
                    fi
                    printf '%sn' "$final"


                    The [[ $str =~ $re ]] does the regex match and updates the captured group array $BASH_REMATCH[@]. So for each of the element in the order of their appearance, we do the string substitution operator $str/old/new. The replacement value in your case is the number multiplied with itself and added by 1.



                    Add more capturing groups to the regex .*([0-9]+) for subsequent matches.




                    If not for a pure bash solution above, using an external utility like perl, one could do it as



                    perl -pe 's/d+/$&*$&+1/ge' <<<"$str"


                    The $& refers to the captured digit in the string and the e flag allows do arithmetic operations over the captured groups.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Nov 11 '18 at 11:35

























                    answered Nov 11 '18 at 10:38









                    InianInian

                    39.1k63971




                    39.1k63971























                        1














                        You can implement this in gawk using match() and substr().



                        echo "a1b2c3" | awk '
                        head = ""
                        tail = $0

                        while (match(tail, /[0-9]+/))
                        num = substr(tail, RSTART, RLENGTH)
                        num = num * num + 1
                        head = head substr(tail, 1, RSTART-1) num
                        tail = substr(tail, RSTART + RLENGTH)


                        print head tail
                        '


                        Output



                        a2b5c10





                        share|improve this answer





























                          1














                          You can implement this in gawk using match() and substr().



                          echo "a1b2c3" | awk '
                          head = ""
                          tail = $0

                          while (match(tail, /[0-9]+/))
                          num = substr(tail, RSTART, RLENGTH)
                          num = num * num + 1
                          head = head substr(tail, 1, RSTART-1) num
                          tail = substr(tail, RSTART + RLENGTH)


                          print head tail
                          '


                          Output



                          a2b5c10





                          share|improve this answer



























                            1












                            1








                            1







                            You can implement this in gawk using match() and substr().



                            echo "a1b2c3" | awk '
                            head = ""
                            tail = $0

                            while (match(tail, /[0-9]+/))
                            num = substr(tail, RSTART, RLENGTH)
                            num = num * num + 1
                            head = head substr(tail, 1, RSTART-1) num
                            tail = substr(tail, RSTART + RLENGTH)


                            print head tail
                            '


                            Output



                            a2b5c10





                            share|improve this answer















                            You can implement this in gawk using match() and substr().



                            echo "a1b2c3" | awk '
                            head = ""
                            tail = $0

                            while (match(tail, /[0-9]+/))
                            num = substr(tail, RSTART, RLENGTH)
                            num = num * num + 1
                            head = head substr(tail, 1, RSTART-1) num
                            tail = substr(tail, RSTART + RLENGTH)


                            print head tail
                            '


                            Output



                            a2b5c10






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Nov 11 '18 at 11:02

























                            answered Nov 11 '18 at 10:34









                            oguzismailoguzismail

                            3,48031125




                            3,48031125





















                                0














                                I am not sure this is my favorite answer, but just to let you know GNU sed does have external command capabilities:



                                echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/echo 1$((2*2+1))3/ge' | sed 's/echo //g'


                                e is the trick to pass the result externally.



                                The most annoying thing - echo is appended when the g and e flags are combined to the substitution groups following the first one, so the second sed gets rid of them. If someone knows if there is something built in that would be great.



                                Unfortunately



                                echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/1$((2*2+1))3/ge'


                                will get a working substitution but throw an error as a2b3c4 is not a command.






                                share|improve this answer



























                                  0














                                  I am not sure this is my favorite answer, but just to let you know GNU sed does have external command capabilities:



                                  echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/echo 1$((2*2+1))3/ge' | sed 's/echo //g'


                                  e is the trick to pass the result externally.



                                  The most annoying thing - echo is appended when the g and e flags are combined to the substitution groups following the first one, so the second sed gets rid of them. If someone knows if there is something built in that would be great.



                                  Unfortunately



                                  echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/1$((2*2+1))3/ge'


                                  will get a working substitution but throw an error as a2b3c4 is not a command.






                                  share|improve this answer

























                                    0












                                    0








                                    0







                                    I am not sure this is my favorite answer, but just to let you know GNU sed does have external command capabilities:



                                    echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/echo 1$((2*2+1))3/ge' | sed 's/echo //g'


                                    e is the trick to pass the result externally.



                                    The most annoying thing - echo is appended when the g and e flags are combined to the substitution groups following the first one, so the second sed gets rid of them. If someone knows if there is something built in that would be great.



                                    Unfortunately



                                    echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/1$((2*2+1))3/ge'


                                    will get a working substitution but throw an error as a2b3c4 is not a command.






                                    share|improve this answer













                                    I am not sure this is my favorite answer, but just to let you know GNU sed does have external command capabilities:



                                    echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/echo 1$((2*2+1))3/ge' | sed 's/echo //g'


                                    e is the trick to pass the result externally.



                                    The most annoying thing - echo is appended when the g and e flags are combined to the substitution groups following the first one, so the second sed gets rid of them. If someone knows if there is something built in that would be great.



                                    Unfortunately



                                    echo "a1b2c3" | sed 's/([^0-9]*)([0-9])([^0-9]*)/1$((2*2+1))3/ge'


                                    will get a working substitution but throw an error as a2b3c4 is not a command.







                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Nov 11 '18 at 10:49









                                    kabanuskabanus

                                    11.4k31339




                                    11.4k31339



























                                        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%2f53247642%2fbash-string-replace-function-similar-to-javascript-string-prototype-replace%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

                                        𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

                                        Edmonton

                                        Crossroads (UK TV series)