Bash parameter expansion











up vote
1
down vote

favorite












I have read/been told that in Bash (4+ in my case) that all parameter expansion functions that are available on strings are available on arrays. Today I was trying to setup a function similar to an array pop. I used something similar to the following syntax:



declare -a arr=( 0 1 2 3 4 5 )
arr=( ${arr[@]:0:(-1)} )


Unexpectedly Bash complained with:



-bash: (-1): substring expression < 0


When I do this with a string the syntax works as expected. For example:



var="see spot run"
var="${var:0:(-1)}"
echo "$var"
see spot ru


I know that for the array I could do this instead (and I tested that it works):



declare -a arr=( 0 1 2 3 4 5 )
arr=( ${arr[@]:0:((${#arr[@]}-1))} )
echo ${arr[@]}
0 1 2 3 4


The questions is if all string parameter expansions work on arrays why doesn't the (-1) syntax work as I expect? Am I just over looking something simple here or is there something deeper at play I am missing?










share|improve this question




























    up vote
    1
    down vote

    favorite












    I have read/been told that in Bash (4+ in my case) that all parameter expansion functions that are available on strings are available on arrays. Today I was trying to setup a function similar to an array pop. I used something similar to the following syntax:



    declare -a arr=( 0 1 2 3 4 5 )
    arr=( ${arr[@]:0:(-1)} )


    Unexpectedly Bash complained with:



    -bash: (-1): substring expression < 0


    When I do this with a string the syntax works as expected. For example:



    var="see spot run"
    var="${var:0:(-1)}"
    echo "$var"
    see spot ru


    I know that for the array I could do this instead (and I tested that it works):



    declare -a arr=( 0 1 2 3 4 5 )
    arr=( ${arr[@]:0:((${#arr[@]}-1))} )
    echo ${arr[@]}
    0 1 2 3 4


    The questions is if all string parameter expansions work on arrays why doesn't the (-1) syntax work as I expect? Am I just over looking something simple here or is there something deeper at play I am missing?










    share|improve this question


























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      I have read/been told that in Bash (4+ in my case) that all parameter expansion functions that are available on strings are available on arrays. Today I was trying to setup a function similar to an array pop. I used something similar to the following syntax:



      declare -a arr=( 0 1 2 3 4 5 )
      arr=( ${arr[@]:0:(-1)} )


      Unexpectedly Bash complained with:



      -bash: (-1): substring expression < 0


      When I do this with a string the syntax works as expected. For example:



      var="see spot run"
      var="${var:0:(-1)}"
      echo "$var"
      see spot ru


      I know that for the array I could do this instead (and I tested that it works):



      declare -a arr=( 0 1 2 3 4 5 )
      arr=( ${arr[@]:0:((${#arr[@]}-1))} )
      echo ${arr[@]}
      0 1 2 3 4


      The questions is if all string parameter expansions work on arrays why doesn't the (-1) syntax work as I expect? Am I just over looking something simple here or is there something deeper at play I am missing?










      share|improve this question















      I have read/been told that in Bash (4+ in my case) that all parameter expansion functions that are available on strings are available on arrays. Today I was trying to setup a function similar to an array pop. I used something similar to the following syntax:



      declare -a arr=( 0 1 2 3 4 5 )
      arr=( ${arr[@]:0:(-1)} )


      Unexpectedly Bash complained with:



      -bash: (-1): substring expression < 0


      When I do this with a string the syntax works as expected. For example:



      var="see spot run"
      var="${var:0:(-1)}"
      echo "$var"
      see spot ru


      I know that for the array I could do this instead (and I tested that it works):



      declare -a arr=( 0 1 2 3 4 5 )
      arr=( ${arr[@]:0:((${#arr[@]}-1))} )
      echo ${arr[@]}
      0 1 2 3 4


      The questions is if all string parameter expansions work on arrays why doesn't the (-1) syntax work as I expect? Am I just over looking something simple here or is there something deeper at play I am missing?







      bash






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 20 at 13:56









      Rui F Ribeiro

      38.2k1475125




      38.2k1475125










      asked Nov 20 at 12:09









      EnterUserNameHere

      7818




      7818






















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          2
          down vote



          accepted










          The answer to this question seems to be that NOT ALL string parameter expansions work on arrays. After reviewing the comments and reading the Bash Reference Manual (link provided by don_crissti, thanks) there is a caveat for negative indexing on substring expansion. As noted in the Bash manual (Shell Parameter Expansion):




          ${parameter:offset:length}



          This is referred to as Substring Expansion. It expands to up to length characters of the value of parameter starting at the character specified by offset. If parameter is @, an indexed array subscripted by @ or *, or an associative array name, the results differ as described below.



          ...



          If parameter is an indexed array name subscripted by @ or *, the result is the length members of the array beginning with ${parameter[offset]}. A negative offset is taken relative to one greater than the maximum index of the specified array. It is an expansion error if length evaluates to a number less than zero.




          As pointed out by don_crissti, the length evaluation that is done here is not in reference to the length of the string/substring but rather evaluation performed during the assignment of the length attribute. As in don_crissti's example:



          a=2
          printf %s\n "${arr[@]:3:(a+1)}"


          If the arithmetic evaluation portion of the length assignment (a+1) were to result in a negative value or, as in my case, the value itself were statically passed as a negative number it is an expansion error. That being said both of the following would result in an expansion error:



          declare -a arr=( 0 1 2 3 4 5 )
          # length evaluates to (-1)
          a=2
          printf %s\n "${arr[@]:3:(a-3)}"
          -bash: (a-3): substring expression < 0

          # or length is assigned as (-1)
          arr=( ${arr[@]:0:(-1)} )
          -bash: (-1): substring expression < 0


          Per the Bash manual, this is the expected behavior in both cases.






          share|improve this answer























            Your Answer








            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "106"
            };
            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',
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            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%2funix.stackexchange.com%2fquestions%2f482961%2fbash-parameter-expansion%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            2
            down vote



            accepted










            The answer to this question seems to be that NOT ALL string parameter expansions work on arrays. After reviewing the comments and reading the Bash Reference Manual (link provided by don_crissti, thanks) there is a caveat for negative indexing on substring expansion. As noted in the Bash manual (Shell Parameter Expansion):




            ${parameter:offset:length}



            This is referred to as Substring Expansion. It expands to up to length characters of the value of parameter starting at the character specified by offset. If parameter is @, an indexed array subscripted by @ or *, or an associative array name, the results differ as described below.



            ...



            If parameter is an indexed array name subscripted by @ or *, the result is the length members of the array beginning with ${parameter[offset]}. A negative offset is taken relative to one greater than the maximum index of the specified array. It is an expansion error if length evaluates to a number less than zero.




            As pointed out by don_crissti, the length evaluation that is done here is not in reference to the length of the string/substring but rather evaluation performed during the assignment of the length attribute. As in don_crissti's example:



            a=2
            printf %s\n "${arr[@]:3:(a+1)}"


            If the arithmetic evaluation portion of the length assignment (a+1) were to result in a negative value or, as in my case, the value itself were statically passed as a negative number it is an expansion error. That being said both of the following would result in an expansion error:



            declare -a arr=( 0 1 2 3 4 5 )
            # length evaluates to (-1)
            a=2
            printf %s\n "${arr[@]:3:(a-3)}"
            -bash: (a-3): substring expression < 0

            # or length is assigned as (-1)
            arr=( ${arr[@]:0:(-1)} )
            -bash: (-1): substring expression < 0


            Per the Bash manual, this is the expected behavior in both cases.






            share|improve this answer



























              up vote
              2
              down vote



              accepted










              The answer to this question seems to be that NOT ALL string parameter expansions work on arrays. After reviewing the comments and reading the Bash Reference Manual (link provided by don_crissti, thanks) there is a caveat for negative indexing on substring expansion. As noted in the Bash manual (Shell Parameter Expansion):




              ${parameter:offset:length}



              This is referred to as Substring Expansion. It expands to up to length characters of the value of parameter starting at the character specified by offset. If parameter is @, an indexed array subscripted by @ or *, or an associative array name, the results differ as described below.



              ...



              If parameter is an indexed array name subscripted by @ or *, the result is the length members of the array beginning with ${parameter[offset]}. A negative offset is taken relative to one greater than the maximum index of the specified array. It is an expansion error if length evaluates to a number less than zero.




              As pointed out by don_crissti, the length evaluation that is done here is not in reference to the length of the string/substring but rather evaluation performed during the assignment of the length attribute. As in don_crissti's example:



              a=2
              printf %s\n "${arr[@]:3:(a+1)}"


              If the arithmetic evaluation portion of the length assignment (a+1) were to result in a negative value or, as in my case, the value itself were statically passed as a negative number it is an expansion error. That being said both of the following would result in an expansion error:



              declare -a arr=( 0 1 2 3 4 5 )
              # length evaluates to (-1)
              a=2
              printf %s\n "${arr[@]:3:(a-3)}"
              -bash: (a-3): substring expression < 0

              # or length is assigned as (-1)
              arr=( ${arr[@]:0:(-1)} )
              -bash: (-1): substring expression < 0


              Per the Bash manual, this is the expected behavior in both cases.






              share|improve this answer

























                up vote
                2
                down vote



                accepted







                up vote
                2
                down vote



                accepted






                The answer to this question seems to be that NOT ALL string parameter expansions work on arrays. After reviewing the comments and reading the Bash Reference Manual (link provided by don_crissti, thanks) there is a caveat for negative indexing on substring expansion. As noted in the Bash manual (Shell Parameter Expansion):




                ${parameter:offset:length}



                This is referred to as Substring Expansion. It expands to up to length characters of the value of parameter starting at the character specified by offset. If parameter is @, an indexed array subscripted by @ or *, or an associative array name, the results differ as described below.



                ...



                If parameter is an indexed array name subscripted by @ or *, the result is the length members of the array beginning with ${parameter[offset]}. A negative offset is taken relative to one greater than the maximum index of the specified array. It is an expansion error if length evaluates to a number less than zero.




                As pointed out by don_crissti, the length evaluation that is done here is not in reference to the length of the string/substring but rather evaluation performed during the assignment of the length attribute. As in don_crissti's example:



                a=2
                printf %s\n "${arr[@]:3:(a+1)}"


                If the arithmetic evaluation portion of the length assignment (a+1) were to result in a negative value or, as in my case, the value itself were statically passed as a negative number it is an expansion error. That being said both of the following would result in an expansion error:



                declare -a arr=( 0 1 2 3 4 5 )
                # length evaluates to (-1)
                a=2
                printf %s\n "${arr[@]:3:(a-3)}"
                -bash: (a-3): substring expression < 0

                # or length is assigned as (-1)
                arr=( ${arr[@]:0:(-1)} )
                -bash: (-1): substring expression < 0


                Per the Bash manual, this is the expected behavior in both cases.






                share|improve this answer














                The answer to this question seems to be that NOT ALL string parameter expansions work on arrays. After reviewing the comments and reading the Bash Reference Manual (link provided by don_crissti, thanks) there is a caveat for negative indexing on substring expansion. As noted in the Bash manual (Shell Parameter Expansion):




                ${parameter:offset:length}



                This is referred to as Substring Expansion. It expands to up to length characters of the value of parameter starting at the character specified by offset. If parameter is @, an indexed array subscripted by @ or *, or an associative array name, the results differ as described below.



                ...



                If parameter is an indexed array name subscripted by @ or *, the result is the length members of the array beginning with ${parameter[offset]}. A negative offset is taken relative to one greater than the maximum index of the specified array. It is an expansion error if length evaluates to a number less than zero.




                As pointed out by don_crissti, the length evaluation that is done here is not in reference to the length of the string/substring but rather evaluation performed during the assignment of the length attribute. As in don_crissti's example:



                a=2
                printf %s\n "${arr[@]:3:(a+1)}"


                If the arithmetic evaluation portion of the length assignment (a+1) were to result in a negative value or, as in my case, the value itself were statically passed as a negative number it is an expansion error. That being said both of the following would result in an expansion error:



                declare -a arr=( 0 1 2 3 4 5 )
                # length evaluates to (-1)
                a=2
                printf %s\n "${arr[@]:3:(a-3)}"
                -bash: (a-3): substring expression < 0

                # or length is assigned as (-1)
                arr=( ${arr[@]:0:(-1)} )
                -bash: (-1): substring expression < 0


                Per the Bash manual, this is the expected behavior in both cases.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 21 at 12:10









                ilkkachu

                54k782147




                54k782147










                answered Nov 21 at 11:36









                EnterUserNameHere

                7818




                7818






























                     

                    draft saved


                    draft discarded



















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f482961%2fbash-parameter-expansion%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

                    Morgemoulin

                    Scott Moir

                    Souastre