Bash - reverse an array












10















Is there a simple way to reverse an array?



#!/bin/bash

array=(1 2 3 4 5 6 7)

echo "${array[@]}"


so I would get: 7 6 5 4 3 2 1

instead of: 1 2 3 4 5 6 7










share|improve this question





























    10















    Is there a simple way to reverse an array?



    #!/bin/bash

    array=(1 2 3 4 5 6 7)

    echo "${array[@]}"


    so I would get: 7 6 5 4 3 2 1

    instead of: 1 2 3 4 5 6 7










    share|improve this question



























      10












      10








      10


      3






      Is there a simple way to reverse an array?



      #!/bin/bash

      array=(1 2 3 4 5 6 7)

      echo "${array[@]}"


      so I would get: 7 6 5 4 3 2 1

      instead of: 1 2 3 4 5 6 7










      share|improve this question
















      Is there a simple way to reverse an array?



      #!/bin/bash

      array=(1 2 3 4 5 6 7)

      echo "${array[@]}"


      so I would get: 7 6 5 4 3 2 1

      instead of: 1 2 3 4 5 6 7







      bash shell-script array bash-array






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Dec 25 '17 at 1:55









      jimmij

      31.2k871106




      31.2k871106










      asked Dec 25 '17 at 0:53









      nathnath

      945625




      945625






















          9 Answers
          9






          active

          oldest

          votes


















          10














          I have answered the question as written, and this code reverses the array. (Printing the elements in reverse order without reversing the array is just a for loop counting down from the last element to zero.) This is a standard "swap first and last" algorithm.



          array=(1 2 3 4 5 6 7)

          min=0
          max=$(( ${#array[@]} -1 ))

          while [[ min -lt max ]]
          do
          # Swap current first and last elements
          x="${array[$min]}"
          array[$min]="${array[$max]}"
          array[$max]="$x"

          # Move closer
          (( min++, max-- ))
          done

          echo "${array[@]}"


          It works for arrays of odd and even length.






          share|improve this answer


























          • Please make a note that this doesn't work for sparse arrays.

            – Isaac
            Dec 25 '17 at 20:38











          • @Isaac there's a solution on StackOverflow if you need to handle those.

            – roaima
            Dec 25 '17 at 22:45











          • Solved here.

            – Isaac
            Sep 10 '18 at 5:05





















          12














          Another unconventional approach:



          #!/bin/bash

          array=(1 2 3 4 5 6 7)

          f() { array=("${BASH_ARGV[@]}"); }

          shopt -s extdebug
          f "${array[@]}"
          shopt -u extdebug

          echo "${array[@]}"


          Output:




          7 6 5 4 3 2 1


          If extdebug is enabled, array BASH_ARGV contains in a function all positional parameters in reverse order.






          share|improve this answer

































            11














            Unconventional approach (all not pure bash):





            • if all elements in an array are just one characters (like in the question) you can use rev:



              echo "${array[@]}" | rev



            • otherwise:



              printf '%sn' "${array[@]}" | tac | tr 'n' ' '; echo



            • and if you can use zsh:



              echo ${(Oa)array}







            share|improve this answer
























            • just been looking up tac, as the opposite of cat quite good to remember, THANKS!

              – nath
              Dec 25 '17 at 2:17






            • 1





              Though i like the idea of rev, i need to mention that rev will not work correctly for numbers with two digits. For example an array element of 12 using rev will be printed as 21. Give it a try ;-)

              – George Vasiliou
              Dec 26 '17 at 21:46











            • @GeorgeVasiliou Yes, that will work only if all elements are one characters (numbers, letters, punctations, ...). That's why I gave also second, more general solution.

              – jimmij
              Dec 26 '17 at 22:04



















            8














            If you actually want the reverse in another array:



            reverse() {
            # first argument is the array to reverse
            # second is the output array
            declare -n arr="$1" rev="$2"
            for i in "${arr[@]}"
            do
            rev=("$i" "${rev[@]}")
            done
            }


            Then:



            array=(1 2 3 4)
            reverse array foo
            echo "${foo[@]}"


            Gives:



            4 3 2 1


            This should correctly handle cases where an array index is missing, say you had array=([1]=1 [2]=2 [4]=4), in which case looping from 0 to the highest index may add additional, empty, elements.






            share|improve this answer
























            • Thanks for this one, it works pretty well, though for some reason shellcheck prints two warnings: array=(1 2 3 4) <-- SC2034: array appears unused. Verify it or export it. and for: echo "${foo[@]}" <-- SC2154: foo is referenced but not assigned.

              – nath
              Dec 26 '17 at 23:15






            • 1





              @nath they're indirectly used, that's what the declare line is for.

              – muru
              Dec 27 '17 at 0:37











            • Clever, but note that declare -n seems not to work in bash versions before 4.3.

              – G-Man
              Sep 9 '18 at 21:33



















            7














            To swap the array positions in place (even with sparse arrays)(since bash 3.0):



            #!/bin/bash
            # Declare an sparse array to test:
            array=([5]=1 [6]=2 [10]=3 [11]=4 [20]=5 [21]=6 [40]=7)
            declare -p array

            scan=("${!array[@]}") # non-sparse array of indexes.

            min=0; max=$(( ${#scan[@]} - 1 )) # for all (indexed) elements.
            while [[ min -lt max ]]
            do
            x="${array[scan[min]]}" # temp variable
            array[scan[min]]="${array[scan[max]]}" # Exchange first and last
            array[scan[max]]="$x" #
            (( min++, max-- )) # Move closer
            done

            declare -p array
            echo "Final Array swapped in-place"
            echo "${array[@]}"


            On execution:



            ./script
            declare -a array=([5]="1" [6]="2" [10]="3" [11]="4" [20]="5" [21]="6" [40]="7")
            declare -a array=([5]="7" [6]="6" [10]="5" [11]="4" [20]="3" [21]="2" [40]="1")
            Final Array swapped in place
            7 6 5 4 3 2 1


            For older bash, you need to use a loop (in bash (since 2.04)) and using $a to avoid the trailing space:



            #!/bin/bash

            array=(1 2 3 4 5 6 7)
            last=${#array[@]}

            a=""
            for (( i=last-1 ; i>=0 ; i-- ));do
            printf '%s%s ' "$a" "${array[i]}"
            a=" "
            done
            echo


            For bash since 2.03:



            #!/bin/bash
            array=(1 2 3 4 5 6 7)
            last=${#array[@]}

            a="";i=0
            while [[ last -ge $((i+=1)) ]]; do
            printf '%s%s' "$a" "${array[ last-i ]}"
            a=" "
            done
            echo


            Also (using the negate operator) (since bash 4.2+):



            #!/bin/bash
            array=(1 2 3 4 5 6 7)
            last=${#array[@]}

            a=""
            for (( i=0 ; i<last ; i++ )); do
            printf '%s%s' "$a" "${array[~i]}"
            a=" "
            done
            echo





            share|improve this answer


























            • Addressing an array’s elements from the end backwards with negative subscripts  seems not to work in bash versions before 4.3.

              – G-Man
              Sep 9 '18 at 21:14











            • Actually, addressing negative numbers was changed in 4.2-alpha. And the script with negated values works from that version. @G-Man p. Negative subscripts to indexed arrays, now treated as offsets from the maximum assigned index + 1. but Bash-hackers reports incorrectly 4.1 numerically indexed arrays can be accessed from the end using negative indexes

              – Isaac
              Sep 10 '18 at 4:31





















            2














            Ugly, unmaintainable, but one-liner:



            eval eval echo "'"${array['{$((${#array[@]}-1))..0}']}"'"





            share|improve this answer































              1














              Though i am not going to tell something new and i will also use tac to reverse the array, i though that would be worthing to mention bellow single line solution using bash version 4.4:



              $ read -d'n' -a array < <(printf '%sn' "${array[@]}" |tac)


              Testing:



              $ array=(1 2 3 4 5 6 10 11 12)
              $ echo "${array[@]}"
              1 2 3 4 5 6 10 11 12
              $ read -d'n' -a array < <(printf '%sn' "${array[@]}"|tac)
              $ echo "${array[@]}"
              12 11 10 6 5 4 3 2 1


              Mind that the var name inside read is the name as the original array, so no helper array is required for temp storage.



              Alternative implementation by adjusting IFS :



              $ IFS=$'n' read -d '' -a array < <(printf '%sn' "${array[@]}"|tac);declare -p array
              declare -a array=([0]="12" [1]="11" [2]="10" [3]="6" [4]="5" [5]="4" [6]="3" [7]="2" [8]="1")


              PS: I think above solutions will not work in bash bellow version 4.4 due to different read bash builtin function implementation.






              share|improve this answer


























              • The IFS version works but it is also printing: declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12"). Using bash 4.4-5. You got to remove ;declare -p array at the end of the first line, then it works...

                – nath
                Dec 26 '17 at 22:59








              • 1





                @nath declare -p is just a quick way to make bash print the real array (index and contents). You don't need this declare -p command in your real script. If something goes wrong in your arrays assignments you could end up in a case that ${array[0]}="1 2 3 4 5 6 10 11 12" = all values stored in the same index - using echo you will see no difference. For a quick array printout using declare -p array will return you the real array indeces and the corresponding value in each index.

                – George Vasiliou
                Dec 26 '17 at 23:17











              • @nath By the way, the read -d'n' method did not work for you?

                – George Vasiliou
                Dec 26 '17 at 23:18











              • read -d'n' works fine.

                – nath
                Dec 26 '17 at 23:23













              • ahhh got you! SORRY :-)

                – nath
                Dec 26 '17 at 23:25



















              1














              To reverse an arbitrary array (which may contain any number of elements with any values):



              With zsh:



              array_reversed=("${(@Oa)array}")


              With bash 4.4+, given that bash variables can't contain NUL bytes anyway, you can use GNU tac -s '' on the elements printed as NUL delimited records:



              readarray -td '' array_reversed < <(
              ((${#array[@]})) && printf '%s' "${array[@]}" | tac -s '')


              POSIXly, to reverse the POSIX shell array ($@, made of $1, $2...):



              code='set --'
              n=$#
              while [ "$n" -gt 0 ]; do
              code="$code "${$n}""
              n=$((n - 1))
              done
              eval "$code"





              share|improve this answer































                0














                Bash



                array=(1 2 3 4 5 6 7)
                echo "${array[@]} " | tac -s ' '


                Or



                array=(1 2 3 4 5 6 7)
                reverse=$(echo "${array[@]} " | tac -s ' ')
                echo ${reverse[@]}


                Result



                7 6 5 4 3 2 1



                Version



                $ tac --version
                tac (GNU coreutils) 8.28





                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',
                  autoActivateHeartbeat: false,
                  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%2f412868%2fbash-reverse-an-array%23new-answer', 'question_page');
                  }
                  );

                  Post as a guest















                  Required, but never shown

























                  9 Answers
                  9






                  active

                  oldest

                  votes








                  9 Answers
                  9






                  active

                  oldest

                  votes









                  active

                  oldest

                  votes






                  active

                  oldest

                  votes









                  10














                  I have answered the question as written, and this code reverses the array. (Printing the elements in reverse order without reversing the array is just a for loop counting down from the last element to zero.) This is a standard "swap first and last" algorithm.



                  array=(1 2 3 4 5 6 7)

                  min=0
                  max=$(( ${#array[@]} -1 ))

                  while [[ min -lt max ]]
                  do
                  # Swap current first and last elements
                  x="${array[$min]}"
                  array[$min]="${array[$max]}"
                  array[$max]="$x"

                  # Move closer
                  (( min++, max-- ))
                  done

                  echo "${array[@]}"


                  It works for arrays of odd and even length.






                  share|improve this answer


























                  • Please make a note that this doesn't work for sparse arrays.

                    – Isaac
                    Dec 25 '17 at 20:38











                  • @Isaac there's a solution on StackOverflow if you need to handle those.

                    – roaima
                    Dec 25 '17 at 22:45











                  • Solved here.

                    – Isaac
                    Sep 10 '18 at 5:05


















                  10














                  I have answered the question as written, and this code reverses the array. (Printing the elements in reverse order without reversing the array is just a for loop counting down from the last element to zero.) This is a standard "swap first and last" algorithm.



                  array=(1 2 3 4 5 6 7)

                  min=0
                  max=$(( ${#array[@]} -1 ))

                  while [[ min -lt max ]]
                  do
                  # Swap current first and last elements
                  x="${array[$min]}"
                  array[$min]="${array[$max]}"
                  array[$max]="$x"

                  # Move closer
                  (( min++, max-- ))
                  done

                  echo "${array[@]}"


                  It works for arrays of odd and even length.






                  share|improve this answer


























                  • Please make a note that this doesn't work for sparse arrays.

                    – Isaac
                    Dec 25 '17 at 20:38











                  • @Isaac there's a solution on StackOverflow if you need to handle those.

                    – roaima
                    Dec 25 '17 at 22:45











                  • Solved here.

                    – Isaac
                    Sep 10 '18 at 5:05
















                  10












                  10








                  10







                  I have answered the question as written, and this code reverses the array. (Printing the elements in reverse order without reversing the array is just a for loop counting down from the last element to zero.) This is a standard "swap first and last" algorithm.



                  array=(1 2 3 4 5 6 7)

                  min=0
                  max=$(( ${#array[@]} -1 ))

                  while [[ min -lt max ]]
                  do
                  # Swap current first and last elements
                  x="${array[$min]}"
                  array[$min]="${array[$max]}"
                  array[$max]="$x"

                  # Move closer
                  (( min++, max-- ))
                  done

                  echo "${array[@]}"


                  It works for arrays of odd and even length.






                  share|improve this answer















                  I have answered the question as written, and this code reverses the array. (Printing the elements in reverse order without reversing the array is just a for loop counting down from the last element to zero.) This is a standard "swap first and last" algorithm.



                  array=(1 2 3 4 5 6 7)

                  min=0
                  max=$(( ${#array[@]} -1 ))

                  while [[ min -lt max ]]
                  do
                  # Swap current first and last elements
                  x="${array[$min]}"
                  array[$min]="${array[$max]}"
                  array[$max]="$x"

                  # Move closer
                  (( min++, max-- ))
                  done

                  echo "${array[@]}"


                  It works for arrays of odd and even length.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Dec 25 '17 at 2:17

























                  answered Dec 25 '17 at 1:07









                  roaimaroaima

                  44.1k555119




                  44.1k555119













                  • Please make a note that this doesn't work for sparse arrays.

                    – Isaac
                    Dec 25 '17 at 20:38











                  • @Isaac there's a solution on StackOverflow if you need to handle those.

                    – roaima
                    Dec 25 '17 at 22:45











                  • Solved here.

                    – Isaac
                    Sep 10 '18 at 5:05





















                  • Please make a note that this doesn't work for sparse arrays.

                    – Isaac
                    Dec 25 '17 at 20:38











                  • @Isaac there's a solution on StackOverflow if you need to handle those.

                    – roaima
                    Dec 25 '17 at 22:45











                  • Solved here.

                    – Isaac
                    Sep 10 '18 at 5:05



















                  Please make a note that this doesn't work for sparse arrays.

                  – Isaac
                  Dec 25 '17 at 20:38





                  Please make a note that this doesn't work for sparse arrays.

                  – Isaac
                  Dec 25 '17 at 20:38













                  @Isaac there's a solution on StackOverflow if you need to handle those.

                  – roaima
                  Dec 25 '17 at 22:45





                  @Isaac there's a solution on StackOverflow if you need to handle those.

                  – roaima
                  Dec 25 '17 at 22:45













                  Solved here.

                  – Isaac
                  Sep 10 '18 at 5:05







                  Solved here.

                  – Isaac
                  Sep 10 '18 at 5:05















                  12














                  Another unconventional approach:



                  #!/bin/bash

                  array=(1 2 3 4 5 6 7)

                  f() { array=("${BASH_ARGV[@]}"); }

                  shopt -s extdebug
                  f "${array[@]}"
                  shopt -u extdebug

                  echo "${array[@]}"


                  Output:




                  7 6 5 4 3 2 1


                  If extdebug is enabled, array BASH_ARGV contains in a function all positional parameters in reverse order.






                  share|improve this answer






























                    12














                    Another unconventional approach:



                    #!/bin/bash

                    array=(1 2 3 4 5 6 7)

                    f() { array=("${BASH_ARGV[@]}"); }

                    shopt -s extdebug
                    f "${array[@]}"
                    shopt -u extdebug

                    echo "${array[@]}"


                    Output:




                    7 6 5 4 3 2 1


                    If extdebug is enabled, array BASH_ARGV contains in a function all positional parameters in reverse order.






                    share|improve this answer




























                      12












                      12








                      12







                      Another unconventional approach:



                      #!/bin/bash

                      array=(1 2 3 4 5 6 7)

                      f() { array=("${BASH_ARGV[@]}"); }

                      shopt -s extdebug
                      f "${array[@]}"
                      shopt -u extdebug

                      echo "${array[@]}"


                      Output:




                      7 6 5 4 3 2 1


                      If extdebug is enabled, array BASH_ARGV contains in a function all positional parameters in reverse order.






                      share|improve this answer















                      Another unconventional approach:



                      #!/bin/bash

                      array=(1 2 3 4 5 6 7)

                      f() { array=("${BASH_ARGV[@]}"); }

                      shopt -s extdebug
                      f "${array[@]}"
                      shopt -u extdebug

                      echo "${array[@]}"


                      Output:




                      7 6 5 4 3 2 1


                      If extdebug is enabled, array BASH_ARGV contains in a function all positional parameters in reverse order.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Dec 25 '17 at 15:50

























                      answered Dec 25 '17 at 5:52









                      CyrusCyrus

                      7,3112837




                      7,3112837























                          11














                          Unconventional approach (all not pure bash):





                          • if all elements in an array are just one characters (like in the question) you can use rev:



                            echo "${array[@]}" | rev



                          • otherwise:



                            printf '%sn' "${array[@]}" | tac | tr 'n' ' '; echo



                          • and if you can use zsh:



                            echo ${(Oa)array}







                          share|improve this answer
























                          • just been looking up tac, as the opposite of cat quite good to remember, THANKS!

                            – nath
                            Dec 25 '17 at 2:17






                          • 1





                            Though i like the idea of rev, i need to mention that rev will not work correctly for numbers with two digits. For example an array element of 12 using rev will be printed as 21. Give it a try ;-)

                            – George Vasiliou
                            Dec 26 '17 at 21:46











                          • @GeorgeVasiliou Yes, that will work only if all elements are one characters (numbers, letters, punctations, ...). That's why I gave also second, more general solution.

                            – jimmij
                            Dec 26 '17 at 22:04
















                          11














                          Unconventional approach (all not pure bash):





                          • if all elements in an array are just one characters (like in the question) you can use rev:



                            echo "${array[@]}" | rev



                          • otherwise:



                            printf '%sn' "${array[@]}" | tac | tr 'n' ' '; echo



                          • and if you can use zsh:



                            echo ${(Oa)array}







                          share|improve this answer
























                          • just been looking up tac, as the opposite of cat quite good to remember, THANKS!

                            – nath
                            Dec 25 '17 at 2:17






                          • 1





                            Though i like the idea of rev, i need to mention that rev will not work correctly for numbers with two digits. For example an array element of 12 using rev will be printed as 21. Give it a try ;-)

                            – George Vasiliou
                            Dec 26 '17 at 21:46











                          • @GeorgeVasiliou Yes, that will work only if all elements are one characters (numbers, letters, punctations, ...). That's why I gave also second, more general solution.

                            – jimmij
                            Dec 26 '17 at 22:04














                          11












                          11








                          11







                          Unconventional approach (all not pure bash):





                          • if all elements in an array are just one characters (like in the question) you can use rev:



                            echo "${array[@]}" | rev



                          • otherwise:



                            printf '%sn' "${array[@]}" | tac | tr 'n' ' '; echo



                          • and if you can use zsh:



                            echo ${(Oa)array}







                          share|improve this answer













                          Unconventional approach (all not pure bash):





                          • if all elements in an array are just one characters (like in the question) you can use rev:



                            echo "${array[@]}" | rev



                          • otherwise:



                            printf '%sn' "${array[@]}" | tac | tr 'n' ' '; echo



                          • and if you can use zsh:



                            echo ${(Oa)array}








                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Dec 25 '17 at 1:52









                          jimmijjimmij

                          31.2k871106




                          31.2k871106













                          • just been looking up tac, as the opposite of cat quite good to remember, THANKS!

                            – nath
                            Dec 25 '17 at 2:17






                          • 1





                            Though i like the idea of rev, i need to mention that rev will not work correctly for numbers with two digits. For example an array element of 12 using rev will be printed as 21. Give it a try ;-)

                            – George Vasiliou
                            Dec 26 '17 at 21:46











                          • @GeorgeVasiliou Yes, that will work only if all elements are one characters (numbers, letters, punctations, ...). That's why I gave also second, more general solution.

                            – jimmij
                            Dec 26 '17 at 22:04



















                          • just been looking up tac, as the opposite of cat quite good to remember, THANKS!

                            – nath
                            Dec 25 '17 at 2:17






                          • 1





                            Though i like the idea of rev, i need to mention that rev will not work correctly for numbers with two digits. For example an array element of 12 using rev will be printed as 21. Give it a try ;-)

                            – George Vasiliou
                            Dec 26 '17 at 21:46











                          • @GeorgeVasiliou Yes, that will work only if all elements are one characters (numbers, letters, punctations, ...). That's why I gave also second, more general solution.

                            – jimmij
                            Dec 26 '17 at 22:04

















                          just been looking up tac, as the opposite of cat quite good to remember, THANKS!

                          – nath
                          Dec 25 '17 at 2:17





                          just been looking up tac, as the opposite of cat quite good to remember, THANKS!

                          – nath
                          Dec 25 '17 at 2:17




                          1




                          1





                          Though i like the idea of rev, i need to mention that rev will not work correctly for numbers with two digits. For example an array element of 12 using rev will be printed as 21. Give it a try ;-)

                          – George Vasiliou
                          Dec 26 '17 at 21:46





                          Though i like the idea of rev, i need to mention that rev will not work correctly for numbers with two digits. For example an array element of 12 using rev will be printed as 21. Give it a try ;-)

                          – George Vasiliou
                          Dec 26 '17 at 21:46













                          @GeorgeVasiliou Yes, that will work only if all elements are one characters (numbers, letters, punctations, ...). That's why I gave also second, more general solution.

                          – jimmij
                          Dec 26 '17 at 22:04





                          @GeorgeVasiliou Yes, that will work only if all elements are one characters (numbers, letters, punctations, ...). That's why I gave also second, more general solution.

                          – jimmij
                          Dec 26 '17 at 22:04











                          8














                          If you actually want the reverse in another array:



                          reverse() {
                          # first argument is the array to reverse
                          # second is the output array
                          declare -n arr="$1" rev="$2"
                          for i in "${arr[@]}"
                          do
                          rev=("$i" "${rev[@]}")
                          done
                          }


                          Then:



                          array=(1 2 3 4)
                          reverse array foo
                          echo "${foo[@]}"


                          Gives:



                          4 3 2 1


                          This should correctly handle cases where an array index is missing, say you had array=([1]=1 [2]=2 [4]=4), in which case looping from 0 to the highest index may add additional, empty, elements.






                          share|improve this answer
























                          • Thanks for this one, it works pretty well, though for some reason shellcheck prints two warnings: array=(1 2 3 4) <-- SC2034: array appears unused. Verify it or export it. and for: echo "${foo[@]}" <-- SC2154: foo is referenced but not assigned.

                            – nath
                            Dec 26 '17 at 23:15






                          • 1





                            @nath they're indirectly used, that's what the declare line is for.

                            – muru
                            Dec 27 '17 at 0:37











                          • Clever, but note that declare -n seems not to work in bash versions before 4.3.

                            – G-Man
                            Sep 9 '18 at 21:33
















                          8














                          If you actually want the reverse in another array:



                          reverse() {
                          # first argument is the array to reverse
                          # second is the output array
                          declare -n arr="$1" rev="$2"
                          for i in "${arr[@]}"
                          do
                          rev=("$i" "${rev[@]}")
                          done
                          }


                          Then:



                          array=(1 2 3 4)
                          reverse array foo
                          echo "${foo[@]}"


                          Gives:



                          4 3 2 1


                          This should correctly handle cases where an array index is missing, say you had array=([1]=1 [2]=2 [4]=4), in which case looping from 0 to the highest index may add additional, empty, elements.






                          share|improve this answer
























                          • Thanks for this one, it works pretty well, though for some reason shellcheck prints two warnings: array=(1 2 3 4) <-- SC2034: array appears unused. Verify it or export it. and for: echo "${foo[@]}" <-- SC2154: foo is referenced but not assigned.

                            – nath
                            Dec 26 '17 at 23:15






                          • 1





                            @nath they're indirectly used, that's what the declare line is for.

                            – muru
                            Dec 27 '17 at 0:37











                          • Clever, but note that declare -n seems not to work in bash versions before 4.3.

                            – G-Man
                            Sep 9 '18 at 21:33














                          8












                          8








                          8







                          If you actually want the reverse in another array:



                          reverse() {
                          # first argument is the array to reverse
                          # second is the output array
                          declare -n arr="$1" rev="$2"
                          for i in "${arr[@]}"
                          do
                          rev=("$i" "${rev[@]}")
                          done
                          }


                          Then:



                          array=(1 2 3 4)
                          reverse array foo
                          echo "${foo[@]}"


                          Gives:



                          4 3 2 1


                          This should correctly handle cases where an array index is missing, say you had array=([1]=1 [2]=2 [4]=4), in which case looping from 0 to the highest index may add additional, empty, elements.






                          share|improve this answer













                          If you actually want the reverse in another array:



                          reverse() {
                          # first argument is the array to reverse
                          # second is the output array
                          declare -n arr="$1" rev="$2"
                          for i in "${arr[@]}"
                          do
                          rev=("$i" "${rev[@]}")
                          done
                          }


                          Then:



                          array=(1 2 3 4)
                          reverse array foo
                          echo "${foo[@]}"


                          Gives:



                          4 3 2 1


                          This should correctly handle cases where an array index is missing, say you had array=([1]=1 [2]=2 [4]=4), in which case looping from 0 to the highest index may add additional, empty, elements.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Dec 25 '17 at 9:20









                          murumuru

                          1




                          1













                          • Thanks for this one, it works pretty well, though for some reason shellcheck prints two warnings: array=(1 2 3 4) <-- SC2034: array appears unused. Verify it or export it. and for: echo "${foo[@]}" <-- SC2154: foo is referenced but not assigned.

                            – nath
                            Dec 26 '17 at 23:15






                          • 1





                            @nath they're indirectly used, that's what the declare line is for.

                            – muru
                            Dec 27 '17 at 0:37











                          • Clever, but note that declare -n seems not to work in bash versions before 4.3.

                            – G-Man
                            Sep 9 '18 at 21:33



















                          • Thanks for this one, it works pretty well, though for some reason shellcheck prints two warnings: array=(1 2 3 4) <-- SC2034: array appears unused. Verify it or export it. and for: echo "${foo[@]}" <-- SC2154: foo is referenced but not assigned.

                            – nath
                            Dec 26 '17 at 23:15






                          • 1





                            @nath they're indirectly used, that's what the declare line is for.

                            – muru
                            Dec 27 '17 at 0:37











                          • Clever, but note that declare -n seems not to work in bash versions before 4.3.

                            – G-Man
                            Sep 9 '18 at 21:33

















                          Thanks for this one, it works pretty well, though for some reason shellcheck prints two warnings: array=(1 2 3 4) <-- SC2034: array appears unused. Verify it or export it. and for: echo "${foo[@]}" <-- SC2154: foo is referenced but not assigned.

                          – nath
                          Dec 26 '17 at 23:15





                          Thanks for this one, it works pretty well, though for some reason shellcheck prints two warnings: array=(1 2 3 4) <-- SC2034: array appears unused. Verify it or export it. and for: echo "${foo[@]}" <-- SC2154: foo is referenced but not assigned.

                          – nath
                          Dec 26 '17 at 23:15




                          1




                          1





                          @nath they're indirectly used, that's what the declare line is for.

                          – muru
                          Dec 27 '17 at 0:37





                          @nath they're indirectly used, that's what the declare line is for.

                          – muru
                          Dec 27 '17 at 0:37













                          Clever, but note that declare -n seems not to work in bash versions before 4.3.

                          – G-Man
                          Sep 9 '18 at 21:33





                          Clever, but note that declare -n seems not to work in bash versions before 4.3.

                          – G-Man
                          Sep 9 '18 at 21:33











                          7














                          To swap the array positions in place (even with sparse arrays)(since bash 3.0):



                          #!/bin/bash
                          # Declare an sparse array to test:
                          array=([5]=1 [6]=2 [10]=3 [11]=4 [20]=5 [21]=6 [40]=7)
                          declare -p array

                          scan=("${!array[@]}") # non-sparse array of indexes.

                          min=0; max=$(( ${#scan[@]} - 1 )) # for all (indexed) elements.
                          while [[ min -lt max ]]
                          do
                          x="${array[scan[min]]}" # temp variable
                          array[scan[min]]="${array[scan[max]]}" # Exchange first and last
                          array[scan[max]]="$x" #
                          (( min++, max-- )) # Move closer
                          done

                          declare -p array
                          echo "Final Array swapped in-place"
                          echo "${array[@]}"


                          On execution:



                          ./script
                          declare -a array=([5]="1" [6]="2" [10]="3" [11]="4" [20]="5" [21]="6" [40]="7")
                          declare -a array=([5]="7" [6]="6" [10]="5" [11]="4" [20]="3" [21]="2" [40]="1")
                          Final Array swapped in place
                          7 6 5 4 3 2 1


                          For older bash, you need to use a loop (in bash (since 2.04)) and using $a to avoid the trailing space:



                          #!/bin/bash

                          array=(1 2 3 4 5 6 7)
                          last=${#array[@]}

                          a=""
                          for (( i=last-1 ; i>=0 ; i-- ));do
                          printf '%s%s ' "$a" "${array[i]}"
                          a=" "
                          done
                          echo


                          For bash since 2.03:



                          #!/bin/bash
                          array=(1 2 3 4 5 6 7)
                          last=${#array[@]}

                          a="";i=0
                          while [[ last -ge $((i+=1)) ]]; do
                          printf '%s%s' "$a" "${array[ last-i ]}"
                          a=" "
                          done
                          echo


                          Also (using the negate operator) (since bash 4.2+):



                          #!/bin/bash
                          array=(1 2 3 4 5 6 7)
                          last=${#array[@]}

                          a=""
                          for (( i=0 ; i<last ; i++ )); do
                          printf '%s%s' "$a" "${array[~i]}"
                          a=" "
                          done
                          echo





                          share|improve this answer


























                          • Addressing an array’s elements from the end backwards with negative subscripts  seems not to work in bash versions before 4.3.

                            – G-Man
                            Sep 9 '18 at 21:14











                          • Actually, addressing negative numbers was changed in 4.2-alpha. And the script with negated values works from that version. @G-Man p. Negative subscripts to indexed arrays, now treated as offsets from the maximum assigned index + 1. but Bash-hackers reports incorrectly 4.1 numerically indexed arrays can be accessed from the end using negative indexes

                            – Isaac
                            Sep 10 '18 at 4:31


















                          7














                          To swap the array positions in place (even with sparse arrays)(since bash 3.0):



                          #!/bin/bash
                          # Declare an sparse array to test:
                          array=([5]=1 [6]=2 [10]=3 [11]=4 [20]=5 [21]=6 [40]=7)
                          declare -p array

                          scan=("${!array[@]}") # non-sparse array of indexes.

                          min=0; max=$(( ${#scan[@]} - 1 )) # for all (indexed) elements.
                          while [[ min -lt max ]]
                          do
                          x="${array[scan[min]]}" # temp variable
                          array[scan[min]]="${array[scan[max]]}" # Exchange first and last
                          array[scan[max]]="$x" #
                          (( min++, max-- )) # Move closer
                          done

                          declare -p array
                          echo "Final Array swapped in-place"
                          echo "${array[@]}"


                          On execution:



                          ./script
                          declare -a array=([5]="1" [6]="2" [10]="3" [11]="4" [20]="5" [21]="6" [40]="7")
                          declare -a array=([5]="7" [6]="6" [10]="5" [11]="4" [20]="3" [21]="2" [40]="1")
                          Final Array swapped in place
                          7 6 5 4 3 2 1


                          For older bash, you need to use a loop (in bash (since 2.04)) and using $a to avoid the trailing space:



                          #!/bin/bash

                          array=(1 2 3 4 5 6 7)
                          last=${#array[@]}

                          a=""
                          for (( i=last-1 ; i>=0 ; i-- ));do
                          printf '%s%s ' "$a" "${array[i]}"
                          a=" "
                          done
                          echo


                          For bash since 2.03:



                          #!/bin/bash
                          array=(1 2 3 4 5 6 7)
                          last=${#array[@]}

                          a="";i=0
                          while [[ last -ge $((i+=1)) ]]; do
                          printf '%s%s' "$a" "${array[ last-i ]}"
                          a=" "
                          done
                          echo


                          Also (using the negate operator) (since bash 4.2+):



                          #!/bin/bash
                          array=(1 2 3 4 5 6 7)
                          last=${#array[@]}

                          a=""
                          for (( i=0 ; i<last ; i++ )); do
                          printf '%s%s' "$a" "${array[~i]}"
                          a=" "
                          done
                          echo





                          share|improve this answer


























                          • Addressing an array’s elements from the end backwards with negative subscripts  seems not to work in bash versions before 4.3.

                            – G-Man
                            Sep 9 '18 at 21:14











                          • Actually, addressing negative numbers was changed in 4.2-alpha. And the script with negated values works from that version. @G-Man p. Negative subscripts to indexed arrays, now treated as offsets from the maximum assigned index + 1. but Bash-hackers reports incorrectly 4.1 numerically indexed arrays can be accessed from the end using negative indexes

                            – Isaac
                            Sep 10 '18 at 4:31
















                          7












                          7








                          7







                          To swap the array positions in place (even with sparse arrays)(since bash 3.0):



                          #!/bin/bash
                          # Declare an sparse array to test:
                          array=([5]=1 [6]=2 [10]=3 [11]=4 [20]=5 [21]=6 [40]=7)
                          declare -p array

                          scan=("${!array[@]}") # non-sparse array of indexes.

                          min=0; max=$(( ${#scan[@]} - 1 )) # for all (indexed) elements.
                          while [[ min -lt max ]]
                          do
                          x="${array[scan[min]]}" # temp variable
                          array[scan[min]]="${array[scan[max]]}" # Exchange first and last
                          array[scan[max]]="$x" #
                          (( min++, max-- )) # Move closer
                          done

                          declare -p array
                          echo "Final Array swapped in-place"
                          echo "${array[@]}"


                          On execution:



                          ./script
                          declare -a array=([5]="1" [6]="2" [10]="3" [11]="4" [20]="5" [21]="6" [40]="7")
                          declare -a array=([5]="7" [6]="6" [10]="5" [11]="4" [20]="3" [21]="2" [40]="1")
                          Final Array swapped in place
                          7 6 5 4 3 2 1


                          For older bash, you need to use a loop (in bash (since 2.04)) and using $a to avoid the trailing space:



                          #!/bin/bash

                          array=(1 2 3 4 5 6 7)
                          last=${#array[@]}

                          a=""
                          for (( i=last-1 ; i>=0 ; i-- ));do
                          printf '%s%s ' "$a" "${array[i]}"
                          a=" "
                          done
                          echo


                          For bash since 2.03:



                          #!/bin/bash
                          array=(1 2 3 4 5 6 7)
                          last=${#array[@]}

                          a="";i=0
                          while [[ last -ge $((i+=1)) ]]; do
                          printf '%s%s' "$a" "${array[ last-i ]}"
                          a=" "
                          done
                          echo


                          Also (using the negate operator) (since bash 4.2+):



                          #!/bin/bash
                          array=(1 2 3 4 5 6 7)
                          last=${#array[@]}

                          a=""
                          for (( i=0 ; i<last ; i++ )); do
                          printf '%s%s' "$a" "${array[~i]}"
                          a=" "
                          done
                          echo





                          share|improve this answer















                          To swap the array positions in place (even with sparse arrays)(since bash 3.0):



                          #!/bin/bash
                          # Declare an sparse array to test:
                          array=([5]=1 [6]=2 [10]=3 [11]=4 [20]=5 [21]=6 [40]=7)
                          declare -p array

                          scan=("${!array[@]}") # non-sparse array of indexes.

                          min=0; max=$(( ${#scan[@]} - 1 )) # for all (indexed) elements.
                          while [[ min -lt max ]]
                          do
                          x="${array[scan[min]]}" # temp variable
                          array[scan[min]]="${array[scan[max]]}" # Exchange first and last
                          array[scan[max]]="$x" #
                          (( min++, max-- )) # Move closer
                          done

                          declare -p array
                          echo "Final Array swapped in-place"
                          echo "${array[@]}"


                          On execution:



                          ./script
                          declare -a array=([5]="1" [6]="2" [10]="3" [11]="4" [20]="5" [21]="6" [40]="7")
                          declare -a array=([5]="7" [6]="6" [10]="5" [11]="4" [20]="3" [21]="2" [40]="1")
                          Final Array swapped in place
                          7 6 5 4 3 2 1


                          For older bash, you need to use a loop (in bash (since 2.04)) and using $a to avoid the trailing space:



                          #!/bin/bash

                          array=(1 2 3 4 5 6 7)
                          last=${#array[@]}

                          a=""
                          for (( i=last-1 ; i>=0 ; i-- ));do
                          printf '%s%s ' "$a" "${array[i]}"
                          a=" "
                          done
                          echo


                          For bash since 2.03:



                          #!/bin/bash
                          array=(1 2 3 4 5 6 7)
                          last=${#array[@]}

                          a="";i=0
                          while [[ last -ge $((i+=1)) ]]; do
                          printf '%s%s' "$a" "${array[ last-i ]}"
                          a=" "
                          done
                          echo


                          Also (using the negate operator) (since bash 4.2+):



                          #!/bin/bash
                          array=(1 2 3 4 5 6 7)
                          last=${#array[@]}

                          a=""
                          for (( i=0 ; i<last ; i++ )); do
                          printf '%s%s' "$a" "${array[~i]}"
                          a=" "
                          done
                          echo






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Sep 10 '18 at 5:03

























                          answered Dec 25 '17 at 1:12









                          IsaacIsaac

                          11.8k11752




                          11.8k11752













                          • Addressing an array’s elements from the end backwards with negative subscripts  seems not to work in bash versions before 4.3.

                            – G-Man
                            Sep 9 '18 at 21:14











                          • Actually, addressing negative numbers was changed in 4.2-alpha. And the script with negated values works from that version. @G-Man p. Negative subscripts to indexed arrays, now treated as offsets from the maximum assigned index + 1. but Bash-hackers reports incorrectly 4.1 numerically indexed arrays can be accessed from the end using negative indexes

                            – Isaac
                            Sep 10 '18 at 4:31





















                          • Addressing an array’s elements from the end backwards with negative subscripts  seems not to work in bash versions before 4.3.

                            – G-Man
                            Sep 9 '18 at 21:14











                          • Actually, addressing negative numbers was changed in 4.2-alpha. And the script with negated values works from that version. @G-Man p. Negative subscripts to indexed arrays, now treated as offsets from the maximum assigned index + 1. but Bash-hackers reports incorrectly 4.1 numerically indexed arrays can be accessed from the end using negative indexes

                            – Isaac
                            Sep 10 '18 at 4:31



















                          Addressing an array’s elements from the end backwards with negative subscripts  seems not to work in bash versions before 4.3.

                          – G-Man
                          Sep 9 '18 at 21:14





                          Addressing an array’s elements from the end backwards with negative subscripts  seems not to work in bash versions before 4.3.

                          – G-Man
                          Sep 9 '18 at 21:14













                          Actually, addressing negative numbers was changed in 4.2-alpha. And the script with negated values works from that version. @G-Man p. Negative subscripts to indexed arrays, now treated as offsets from the maximum assigned index + 1. but Bash-hackers reports incorrectly 4.1 numerically indexed arrays can be accessed from the end using negative indexes

                          – Isaac
                          Sep 10 '18 at 4:31







                          Actually, addressing negative numbers was changed in 4.2-alpha. And the script with negated values works from that version. @G-Man p. Negative subscripts to indexed arrays, now treated as offsets from the maximum assigned index + 1. but Bash-hackers reports incorrectly 4.1 numerically indexed arrays can be accessed from the end using negative indexes

                          – Isaac
                          Sep 10 '18 at 4:31













                          2














                          Ugly, unmaintainable, but one-liner:



                          eval eval echo "'"${array['{$((${#array[@]}-1))..0}']}"'"





                          share|improve this answer




























                            2














                            Ugly, unmaintainable, but one-liner:



                            eval eval echo "'"${array['{$((${#array[@]}-1))..0}']}"'"





                            share|improve this answer


























                              2












                              2








                              2







                              Ugly, unmaintainable, but one-liner:



                              eval eval echo "'"${array['{$((${#array[@]}-1))..0}']}"'"





                              share|improve this answer













                              Ugly, unmaintainable, but one-liner:



                              eval eval echo "'"${array['{$((${#array[@]}-1))..0}']}"'"






                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Dec 27 '17 at 16:09









                              user23013user23013

                              627412




                              627412























                                  1














                                  Though i am not going to tell something new and i will also use tac to reverse the array, i though that would be worthing to mention bellow single line solution using bash version 4.4:



                                  $ read -d'n' -a array < <(printf '%sn' "${array[@]}" |tac)


                                  Testing:



                                  $ array=(1 2 3 4 5 6 10 11 12)
                                  $ echo "${array[@]}"
                                  1 2 3 4 5 6 10 11 12
                                  $ read -d'n' -a array < <(printf '%sn' "${array[@]}"|tac)
                                  $ echo "${array[@]}"
                                  12 11 10 6 5 4 3 2 1


                                  Mind that the var name inside read is the name as the original array, so no helper array is required for temp storage.



                                  Alternative implementation by adjusting IFS :



                                  $ IFS=$'n' read -d '' -a array < <(printf '%sn' "${array[@]}"|tac);declare -p array
                                  declare -a array=([0]="12" [1]="11" [2]="10" [3]="6" [4]="5" [5]="4" [6]="3" [7]="2" [8]="1")


                                  PS: I think above solutions will not work in bash bellow version 4.4 due to different read bash builtin function implementation.






                                  share|improve this answer


























                                  • The IFS version works but it is also printing: declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12"). Using bash 4.4-5. You got to remove ;declare -p array at the end of the first line, then it works...

                                    – nath
                                    Dec 26 '17 at 22:59








                                  • 1





                                    @nath declare -p is just a quick way to make bash print the real array (index and contents). You don't need this declare -p command in your real script. If something goes wrong in your arrays assignments you could end up in a case that ${array[0]}="1 2 3 4 5 6 10 11 12" = all values stored in the same index - using echo you will see no difference. For a quick array printout using declare -p array will return you the real array indeces and the corresponding value in each index.

                                    – George Vasiliou
                                    Dec 26 '17 at 23:17











                                  • @nath By the way, the read -d'n' method did not work for you?

                                    – George Vasiliou
                                    Dec 26 '17 at 23:18











                                  • read -d'n' works fine.

                                    – nath
                                    Dec 26 '17 at 23:23













                                  • ahhh got you! SORRY :-)

                                    – nath
                                    Dec 26 '17 at 23:25
















                                  1














                                  Though i am not going to tell something new and i will also use tac to reverse the array, i though that would be worthing to mention bellow single line solution using bash version 4.4:



                                  $ read -d'n' -a array < <(printf '%sn' "${array[@]}" |tac)


                                  Testing:



                                  $ array=(1 2 3 4 5 6 10 11 12)
                                  $ echo "${array[@]}"
                                  1 2 3 4 5 6 10 11 12
                                  $ read -d'n' -a array < <(printf '%sn' "${array[@]}"|tac)
                                  $ echo "${array[@]}"
                                  12 11 10 6 5 4 3 2 1


                                  Mind that the var name inside read is the name as the original array, so no helper array is required for temp storage.



                                  Alternative implementation by adjusting IFS :



                                  $ IFS=$'n' read -d '' -a array < <(printf '%sn' "${array[@]}"|tac);declare -p array
                                  declare -a array=([0]="12" [1]="11" [2]="10" [3]="6" [4]="5" [5]="4" [6]="3" [7]="2" [8]="1")


                                  PS: I think above solutions will not work in bash bellow version 4.4 due to different read bash builtin function implementation.






                                  share|improve this answer


























                                  • The IFS version works but it is also printing: declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12"). Using bash 4.4-5. You got to remove ;declare -p array at the end of the first line, then it works...

                                    – nath
                                    Dec 26 '17 at 22:59








                                  • 1





                                    @nath declare -p is just a quick way to make bash print the real array (index and contents). You don't need this declare -p command in your real script. If something goes wrong in your arrays assignments you could end up in a case that ${array[0]}="1 2 3 4 5 6 10 11 12" = all values stored in the same index - using echo you will see no difference. For a quick array printout using declare -p array will return you the real array indeces and the corresponding value in each index.

                                    – George Vasiliou
                                    Dec 26 '17 at 23:17











                                  • @nath By the way, the read -d'n' method did not work for you?

                                    – George Vasiliou
                                    Dec 26 '17 at 23:18











                                  • read -d'n' works fine.

                                    – nath
                                    Dec 26 '17 at 23:23













                                  • ahhh got you! SORRY :-)

                                    – nath
                                    Dec 26 '17 at 23:25














                                  1












                                  1








                                  1







                                  Though i am not going to tell something new and i will also use tac to reverse the array, i though that would be worthing to mention bellow single line solution using bash version 4.4:



                                  $ read -d'n' -a array < <(printf '%sn' "${array[@]}" |tac)


                                  Testing:



                                  $ array=(1 2 3 4 5 6 10 11 12)
                                  $ echo "${array[@]}"
                                  1 2 3 4 5 6 10 11 12
                                  $ read -d'n' -a array < <(printf '%sn' "${array[@]}"|tac)
                                  $ echo "${array[@]}"
                                  12 11 10 6 5 4 3 2 1


                                  Mind that the var name inside read is the name as the original array, so no helper array is required for temp storage.



                                  Alternative implementation by adjusting IFS :



                                  $ IFS=$'n' read -d '' -a array < <(printf '%sn' "${array[@]}"|tac);declare -p array
                                  declare -a array=([0]="12" [1]="11" [2]="10" [3]="6" [4]="5" [5]="4" [6]="3" [7]="2" [8]="1")


                                  PS: I think above solutions will not work in bash bellow version 4.4 due to different read bash builtin function implementation.






                                  share|improve this answer















                                  Though i am not going to tell something new and i will also use tac to reverse the array, i though that would be worthing to mention bellow single line solution using bash version 4.4:



                                  $ read -d'n' -a array < <(printf '%sn' "${array[@]}" |tac)


                                  Testing:



                                  $ array=(1 2 3 4 5 6 10 11 12)
                                  $ echo "${array[@]}"
                                  1 2 3 4 5 6 10 11 12
                                  $ read -d'n' -a array < <(printf '%sn' "${array[@]}"|tac)
                                  $ echo "${array[@]}"
                                  12 11 10 6 5 4 3 2 1


                                  Mind that the var name inside read is the name as the original array, so no helper array is required for temp storage.



                                  Alternative implementation by adjusting IFS :



                                  $ IFS=$'n' read -d '' -a array < <(printf '%sn' "${array[@]}"|tac);declare -p array
                                  declare -a array=([0]="12" [1]="11" [2]="10" [3]="6" [4]="5" [5]="4" [6]="3" [7]="2" [8]="1")


                                  PS: I think above solutions will not work in bash bellow version 4.4 due to different read bash builtin function implementation.







                                  share|improve this answer














                                  share|improve this answer



                                  share|improve this answer








                                  edited Dec 26 '17 at 22:24

























                                  answered Dec 26 '17 at 22:14









                                  George VasiliouGeorge Vasiliou

                                  5,66031028




                                  5,66031028













                                  • The IFS version works but it is also printing: declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12"). Using bash 4.4-5. You got to remove ;declare -p array at the end of the first line, then it works...

                                    – nath
                                    Dec 26 '17 at 22:59








                                  • 1





                                    @nath declare -p is just a quick way to make bash print the real array (index and contents). You don't need this declare -p command in your real script. If something goes wrong in your arrays assignments you could end up in a case that ${array[0]}="1 2 3 4 5 6 10 11 12" = all values stored in the same index - using echo you will see no difference. For a quick array printout using declare -p array will return you the real array indeces and the corresponding value in each index.

                                    – George Vasiliou
                                    Dec 26 '17 at 23:17











                                  • @nath By the way, the read -d'n' method did not work for you?

                                    – George Vasiliou
                                    Dec 26 '17 at 23:18











                                  • read -d'n' works fine.

                                    – nath
                                    Dec 26 '17 at 23:23













                                  • ahhh got you! SORRY :-)

                                    – nath
                                    Dec 26 '17 at 23:25



















                                  • The IFS version works but it is also printing: declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12"). Using bash 4.4-5. You got to remove ;declare -p array at the end of the first line, then it works...

                                    – nath
                                    Dec 26 '17 at 22:59








                                  • 1





                                    @nath declare -p is just a quick way to make bash print the real array (index and contents). You don't need this declare -p command in your real script. If something goes wrong in your arrays assignments you could end up in a case that ${array[0]}="1 2 3 4 5 6 10 11 12" = all values stored in the same index - using echo you will see no difference. For a quick array printout using declare -p array will return you the real array indeces and the corresponding value in each index.

                                    – George Vasiliou
                                    Dec 26 '17 at 23:17











                                  • @nath By the way, the read -d'n' method did not work for you?

                                    – George Vasiliou
                                    Dec 26 '17 at 23:18











                                  • read -d'n' works fine.

                                    – nath
                                    Dec 26 '17 at 23:23













                                  • ahhh got you! SORRY :-)

                                    – nath
                                    Dec 26 '17 at 23:25

















                                  The IFS version works but it is also printing: declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12"). Using bash 4.4-5. You got to remove ;declare -p array at the end of the first line, then it works...

                                  – nath
                                  Dec 26 '17 at 22:59







                                  The IFS version works but it is also printing: declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12"). Using bash 4.4-5. You got to remove ;declare -p array at the end of the first line, then it works...

                                  – nath
                                  Dec 26 '17 at 22:59






                                  1




                                  1





                                  @nath declare -p is just a quick way to make bash print the real array (index and contents). You don't need this declare -p command in your real script. If something goes wrong in your arrays assignments you could end up in a case that ${array[0]}="1 2 3 4 5 6 10 11 12" = all values stored in the same index - using echo you will see no difference. For a quick array printout using declare -p array will return you the real array indeces and the corresponding value in each index.

                                  – George Vasiliou
                                  Dec 26 '17 at 23:17





                                  @nath declare -p is just a quick way to make bash print the real array (index and contents). You don't need this declare -p command in your real script. If something goes wrong in your arrays assignments you could end up in a case that ${array[0]}="1 2 3 4 5 6 10 11 12" = all values stored in the same index - using echo you will see no difference. For a quick array printout using declare -p array will return you the real array indeces and the corresponding value in each index.

                                  – George Vasiliou
                                  Dec 26 '17 at 23:17













                                  @nath By the way, the read -d'n' method did not work for you?

                                  – George Vasiliou
                                  Dec 26 '17 at 23:18





                                  @nath By the way, the read -d'n' method did not work for you?

                                  – George Vasiliou
                                  Dec 26 '17 at 23:18













                                  read -d'n' works fine.

                                  – nath
                                  Dec 26 '17 at 23:23







                                  read -d'n' works fine.

                                  – nath
                                  Dec 26 '17 at 23:23















                                  ahhh got you! SORRY :-)

                                  – nath
                                  Dec 26 '17 at 23:25





                                  ahhh got you! SORRY :-)

                                  – nath
                                  Dec 26 '17 at 23:25











                                  1














                                  To reverse an arbitrary array (which may contain any number of elements with any values):



                                  With zsh:



                                  array_reversed=("${(@Oa)array}")


                                  With bash 4.4+, given that bash variables can't contain NUL bytes anyway, you can use GNU tac -s '' on the elements printed as NUL delimited records:



                                  readarray -td '' array_reversed < <(
                                  ((${#array[@]})) && printf '%s' "${array[@]}" | tac -s '')


                                  POSIXly, to reverse the POSIX shell array ($@, made of $1, $2...):



                                  code='set --'
                                  n=$#
                                  while [ "$n" -gt 0 ]; do
                                  code="$code "${$n}""
                                  n=$((n - 1))
                                  done
                                  eval "$code"





                                  share|improve this answer




























                                    1














                                    To reverse an arbitrary array (which may contain any number of elements with any values):



                                    With zsh:



                                    array_reversed=("${(@Oa)array}")


                                    With bash 4.4+, given that bash variables can't contain NUL bytes anyway, you can use GNU tac -s '' on the elements printed as NUL delimited records:



                                    readarray -td '' array_reversed < <(
                                    ((${#array[@]})) && printf '%s' "${array[@]}" | tac -s '')


                                    POSIXly, to reverse the POSIX shell array ($@, made of $1, $2...):



                                    code='set --'
                                    n=$#
                                    while [ "$n" -gt 0 ]; do
                                    code="$code "${$n}""
                                    n=$((n - 1))
                                    done
                                    eval "$code"





                                    share|improve this answer


























                                      1












                                      1








                                      1







                                      To reverse an arbitrary array (which may contain any number of elements with any values):



                                      With zsh:



                                      array_reversed=("${(@Oa)array}")


                                      With bash 4.4+, given that bash variables can't contain NUL bytes anyway, you can use GNU tac -s '' on the elements printed as NUL delimited records:



                                      readarray -td '' array_reversed < <(
                                      ((${#array[@]})) && printf '%s' "${array[@]}" | tac -s '')


                                      POSIXly, to reverse the POSIX shell array ($@, made of $1, $2...):



                                      code='set --'
                                      n=$#
                                      while [ "$n" -gt 0 ]; do
                                      code="$code "${$n}""
                                      n=$((n - 1))
                                      done
                                      eval "$code"





                                      share|improve this answer













                                      To reverse an arbitrary array (which may contain any number of elements with any values):



                                      With zsh:



                                      array_reversed=("${(@Oa)array}")


                                      With bash 4.4+, given that bash variables can't contain NUL bytes anyway, you can use GNU tac -s '' on the elements printed as NUL delimited records:



                                      readarray -td '' array_reversed < <(
                                      ((${#array[@]})) && printf '%s' "${array[@]}" | tac -s '')


                                      POSIXly, to reverse the POSIX shell array ($@, made of $1, $2...):



                                      code='set --'
                                      n=$#
                                      while [ "$n" -gt 0 ]; do
                                      code="$code "${$n}""
                                      n=$((n - 1))
                                      done
                                      eval "$code"






                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered Sep 9 '18 at 20:40









                                      Stéphane ChazelasStéphane Chazelas

                                      303k56570926




                                      303k56570926























                                          0














                                          Bash



                                          array=(1 2 3 4 5 6 7)
                                          echo "${array[@]} " | tac -s ' '


                                          Or



                                          array=(1 2 3 4 5 6 7)
                                          reverse=$(echo "${array[@]} " | tac -s ' ')
                                          echo ${reverse[@]}


                                          Result



                                          7 6 5 4 3 2 1



                                          Version



                                          $ tac --version
                                          tac (GNU coreutils) 8.28





                                          share|improve this answer




























                                            0














                                            Bash



                                            array=(1 2 3 4 5 6 7)
                                            echo "${array[@]} " | tac -s ' '


                                            Or



                                            array=(1 2 3 4 5 6 7)
                                            reverse=$(echo "${array[@]} " | tac -s ' ')
                                            echo ${reverse[@]}


                                            Result



                                            7 6 5 4 3 2 1



                                            Version



                                            $ tac --version
                                            tac (GNU coreutils) 8.28





                                            share|improve this answer


























                                              0












                                              0








                                              0







                                              Bash



                                              array=(1 2 3 4 5 6 7)
                                              echo "${array[@]} " | tac -s ' '


                                              Or



                                              array=(1 2 3 4 5 6 7)
                                              reverse=$(echo "${array[@]} " | tac -s ' ')
                                              echo ${reverse[@]}


                                              Result



                                              7 6 5 4 3 2 1



                                              Version



                                              $ tac --version
                                              tac (GNU coreutils) 8.28





                                              share|improve this answer













                                              Bash



                                              array=(1 2 3 4 5 6 7)
                                              echo "${array[@]} " | tac -s ' '


                                              Or



                                              array=(1 2 3 4 5 6 7)
                                              reverse=$(echo "${array[@]} " | tac -s ' ')
                                              echo ${reverse[@]}


                                              Result



                                              7 6 5 4 3 2 1



                                              Version



                                              $ tac --version
                                              tac (GNU coreutils) 8.28






                                              share|improve this answer












                                              share|improve this answer



                                              share|improve this answer










                                              answered 13 mins ago









                                              monmon

                                              1235




                                              1235






























                                                  draft saved

                                                  draft discarded




















































                                                  Thanks for contributing an answer to Unix & Linux Stack Exchange!


                                                  • 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%2funix.stackexchange.com%2fquestions%2f412868%2fbash-reverse-an-array%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

                                                  CARDNET

                                                  Boot-repair Failure: Unable to locate package grub-common:i386

                                                  濃尾地震