How to get a bash script argument given its position from the end? [duplicate]











up vote
2
down vote

favorite
1













This question already has an answer here:




  • How to get the last argument to a /bin/sh function

    11 answers



  • Get last element of $@ / argv / arguments array without eval [duplicate]

    1 answer




I've got a shell script and I want to use the last argument:



#!/bin/bash
echo My last param is #somehow put it here


Here is what I've tried:



echo $$#
echo ${$#}
echo ${(($#))}


Unfortunately it did not work.



I'm specifically want to understand why my options did not work, I want to do something like double expansion.



In a broader sense, I would like to know how to access the Nth argument from the end. How do I achieve that?










share|improve this question















marked as duplicate by muru, Archemar, G-Man, telcoM, Anthony Geoghegan 16 hours ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















  • Is your question for a solution specific to bash?.
    – Isaac
    yesterday















up vote
2
down vote

favorite
1













This question already has an answer here:




  • How to get the last argument to a /bin/sh function

    11 answers



  • Get last element of $@ / argv / arguments array without eval [duplicate]

    1 answer




I've got a shell script and I want to use the last argument:



#!/bin/bash
echo My last param is #somehow put it here


Here is what I've tried:



echo $$#
echo ${$#}
echo ${(($#))}


Unfortunately it did not work.



I'm specifically want to understand why my options did not work, I want to do something like double expansion.



In a broader sense, I would like to know how to access the Nth argument from the end. How do I achieve that?










share|improve this question















marked as duplicate by muru, Archemar, G-Man, telcoM, Anthony Geoghegan 16 hours ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















  • Is your question for a solution specific to bash?.
    – Isaac
    yesterday













up vote
2
down vote

favorite
1









up vote
2
down vote

favorite
1






1






This question already has an answer here:




  • How to get the last argument to a /bin/sh function

    11 answers



  • Get last element of $@ / argv / arguments array without eval [duplicate]

    1 answer




I've got a shell script and I want to use the last argument:



#!/bin/bash
echo My last param is #somehow put it here


Here is what I've tried:



echo $$#
echo ${$#}
echo ${(($#))}


Unfortunately it did not work.



I'm specifically want to understand why my options did not work, I want to do something like double expansion.



In a broader sense, I would like to know how to access the Nth argument from the end. How do I achieve that?










share|improve this question
















This question already has an answer here:




  • How to get the last argument to a /bin/sh function

    11 answers



  • Get last element of $@ / argv / arguments array without eval [duplicate]

    1 answer




I've got a shell script and I want to use the last argument:



#!/bin/bash
echo My last param is #somehow put it here


Here is what I've tried:



echo $$#
echo ${$#}
echo ${(($#))}


Unfortunately it did not work.



I'm specifically want to understand why my options did not work, I want to do something like double expansion.



In a broader sense, I would like to know how to access the Nth argument from the end. How do I achieve that?





This question already has an answer here:




  • How to get the last argument to a /bin/sh function

    11 answers



  • Get last element of $@ / argv / arguments array without eval [duplicate]

    1 answer








shell-script shell






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 21 hours ago

























asked yesterday









YardenST

1606




1606




marked as duplicate by muru, Archemar, G-Man, telcoM, Anthony Geoghegan 16 hours ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.






marked as duplicate by muru, Archemar, G-Man, telcoM, Anthony Geoghegan 16 hours ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.














  • Is your question for a solution specific to bash?.
    – Isaac
    yesterday


















  • Is your question for a solution specific to bash?.
    – Isaac
    yesterday
















Is your question for a solution specific to bash?.
– Isaac
yesterday




Is your question for a solution specific to bash?.
– Isaac
yesterday










6 Answers
6






active

oldest

votes

















up vote
3
down vote



accepted










In addition (to Kusalananda's answer):



#! /bin/bash 

echo "(bash/ksh): ${@: -1}"
echo "(bash 3.x+): ${!#}"
echo "(bash 3.x+): $BASH_ARGV"
echo "(bash 3.x+/ksh): ${@:$#}"
echo "(bash 3.x+): ${BASH_ARGV[0]}"


and if you worry about portability:



#!/bin/bash

penultimate=''
ultimate=''

for p in "$@" ; do
penultimate="$ultimate"
ultimate="$p"
done

echo "penultimate=$penultimate"
echo "ultimate=$ultimate"





share|improve this answer























  • to Kusalananda's answer.
    – Ljm Dullaart
    yesterday










  • Yes, you're right; I added it in the answer.
    – Ljm Dullaart
    yesterday










  • can you please explain about this notation? ${!#}
    – YardenST
    yesterday










  • @YardenST From the bash manpage: "If the first character of parameter is an exclamation point (!), and parameter is not a nameref, it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion."
    – JoL
    yesterday












  • @YardenST In other words, bash takes #, expands it like it would $#, and then the result (let's say 5) is put through variable expansion again like it would $5.
    – JoL
    yesterday


















up vote
5
down vote













To get any argument from bash script, you can use slicing:



#!/bin/bash

# Get 3rd element from the end
from_end1=3
# Get last element
from_end2=1

# Get slice of array [end - from_end1 : end ] of length 1
echo "${@: -$from_end1: 1}"
echo "${@: -$from_end2: 1}"


You can also use this to get Nth element:



# Get 2nd element
from_beginning=2

echo "${@: $from_beginning: 1}"


Remember to check for length; this might return your program's name or an empty string.






share|improve this answer



















  • 1




    This is bash-specific, right? You should probably note that since the OP's question did not mention bash except in the #! (and in particular didn't use bash tag).
    – R..
    yesterday










  • @R.. Fair point, information added.
    – MatthewRock
    yesterday


















up vote
4
down vote













In bash (release 4.3+), you may assign the passed parameters to an array and access the last one by the index -1:



#!/bin/bash

params=( "$@" )
printf 'The last parameter given to the script is %sn' "${params[-1]}"

foo () {
params=( "$@" )
printf 'The last parameter given to the function is %sn' "${params[-1]}"
}


In general, negative indexes into arrays accesses the elements from the end of the array.






share|improve this answer























  • A negative index might work on bash 4.2+ depending on the patch level. But an slice ${@: -1:1} works with negative indexes since bash 3.0.
    – Isaac
    yesterday










  • @Isaac That's good if you are code golfing, but not if you're writing code that others need to understand and maintain.
    – Kusalananda
    21 hours ago




















up vote
3
down vote













Portable sh, not bash-specific, and without O(n) loops:



eval x=$$(($#-1))


The -1 yields the penultimate argument; replace it with the position you want relative to the end, or drop it entirely if you want the very last one.






share|improve this answer



















  • 1




    One of the very few uses of eval I've ever seen that actually seems merited and safe.
    – Wildcard
    yesterday










  • @Isaac: Updated to note that. Thanks.
    – R..
    yesterday


















up vote
0
down vote













In zsh, the most natural thing, I think, would be:



echo "ultimate: ${@[$#]}"
echo "ultimate: ${@[-1]}"
echo "penultimate: ${@[-2]}"
echo "penultimate: ${@[$(($# - 1))]}"





share|improve this answer




























    up vote
    0
    down vote













    The clasic solutions for POSIX shells (which also work on ksh, zsh or bash) are:



     for last do :;done; echo "last=$last"
    eval "last=$$#"; echo "last=$last"


    For newer shells (ksh93,zsh,bash):



     echo "last=${@: -1}"
    echo "last=${@:(-1)}"
    echo "last=${@:~0}"
    echo "last=${@:$#}"


    Only for:



    bash echo "last=${!#}"
    bash echo "last=$BASH_ARGV"
    zsh echo "last=${@[-1]}"
    zsh echo "last=${@[#]}"



    For the penultimate argument:



     for arg do penultimate=$ultimate; ultimate=$arg; done; echo "$penultimate"
    eval penultimate=$$((#-1))
    echo "${@:$((#-1)):1}"
    echo "${@: -2:1}"
    echo "${@:~1:1}"





    share|improve this answer




























      6 Answers
      6






      active

      oldest

      votes








      6 Answers
      6






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      3
      down vote



      accepted










      In addition (to Kusalananda's answer):



      #! /bin/bash 

      echo "(bash/ksh): ${@: -1}"
      echo "(bash 3.x+): ${!#}"
      echo "(bash 3.x+): $BASH_ARGV"
      echo "(bash 3.x+/ksh): ${@:$#}"
      echo "(bash 3.x+): ${BASH_ARGV[0]}"


      and if you worry about portability:



      #!/bin/bash

      penultimate=''
      ultimate=''

      for p in "$@" ; do
      penultimate="$ultimate"
      ultimate="$p"
      done

      echo "penultimate=$penultimate"
      echo "ultimate=$ultimate"





      share|improve this answer























      • to Kusalananda's answer.
        – Ljm Dullaart
        yesterday










      • Yes, you're right; I added it in the answer.
        – Ljm Dullaart
        yesterday










      • can you please explain about this notation? ${!#}
        – YardenST
        yesterday










      • @YardenST From the bash manpage: "If the first character of parameter is an exclamation point (!), and parameter is not a nameref, it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion."
        – JoL
        yesterday












      • @YardenST In other words, bash takes #, expands it like it would $#, and then the result (let's say 5) is put through variable expansion again like it would $5.
        – JoL
        yesterday















      up vote
      3
      down vote



      accepted










      In addition (to Kusalananda's answer):



      #! /bin/bash 

      echo "(bash/ksh): ${@: -1}"
      echo "(bash 3.x+): ${!#}"
      echo "(bash 3.x+): $BASH_ARGV"
      echo "(bash 3.x+/ksh): ${@:$#}"
      echo "(bash 3.x+): ${BASH_ARGV[0]}"


      and if you worry about portability:



      #!/bin/bash

      penultimate=''
      ultimate=''

      for p in "$@" ; do
      penultimate="$ultimate"
      ultimate="$p"
      done

      echo "penultimate=$penultimate"
      echo "ultimate=$ultimate"





      share|improve this answer























      • to Kusalananda's answer.
        – Ljm Dullaart
        yesterday










      • Yes, you're right; I added it in the answer.
        – Ljm Dullaart
        yesterday










      • can you please explain about this notation? ${!#}
        – YardenST
        yesterday










      • @YardenST From the bash manpage: "If the first character of parameter is an exclamation point (!), and parameter is not a nameref, it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion."
        – JoL
        yesterday












      • @YardenST In other words, bash takes #, expands it like it would $#, and then the result (let's say 5) is put through variable expansion again like it would $5.
        – JoL
        yesterday













      up vote
      3
      down vote



      accepted







      up vote
      3
      down vote



      accepted






      In addition (to Kusalananda's answer):



      #! /bin/bash 

      echo "(bash/ksh): ${@: -1}"
      echo "(bash 3.x+): ${!#}"
      echo "(bash 3.x+): $BASH_ARGV"
      echo "(bash 3.x+/ksh): ${@:$#}"
      echo "(bash 3.x+): ${BASH_ARGV[0]}"


      and if you worry about portability:



      #!/bin/bash

      penultimate=''
      ultimate=''

      for p in "$@" ; do
      penultimate="$ultimate"
      ultimate="$p"
      done

      echo "penultimate=$penultimate"
      echo "ultimate=$ultimate"





      share|improve this answer














      In addition (to Kusalananda's answer):



      #! /bin/bash 

      echo "(bash/ksh): ${@: -1}"
      echo "(bash 3.x+): ${!#}"
      echo "(bash 3.x+): $BASH_ARGV"
      echo "(bash 3.x+/ksh): ${@:$#}"
      echo "(bash 3.x+): ${BASH_ARGV[0]}"


      and if you worry about portability:



      #!/bin/bash

      penultimate=''
      ultimate=''

      for p in "$@" ; do
      penultimate="$ultimate"
      ultimate="$p"
      done

      echo "penultimate=$penultimate"
      echo "ultimate=$ultimate"






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited yesterday









      Kusalananda

      119k16223364




      119k16223364










      answered yesterday









      Ljm Dullaart

      57517




      57517












      • to Kusalananda's answer.
        – Ljm Dullaart
        yesterday










      • Yes, you're right; I added it in the answer.
        – Ljm Dullaart
        yesterday










      • can you please explain about this notation? ${!#}
        – YardenST
        yesterday










      • @YardenST From the bash manpage: "If the first character of parameter is an exclamation point (!), and parameter is not a nameref, it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion."
        – JoL
        yesterday












      • @YardenST In other words, bash takes #, expands it like it would $#, and then the result (let's say 5) is put through variable expansion again like it would $5.
        – JoL
        yesterday


















      • to Kusalananda's answer.
        – Ljm Dullaart
        yesterday










      • Yes, you're right; I added it in the answer.
        – Ljm Dullaart
        yesterday










      • can you please explain about this notation? ${!#}
        – YardenST
        yesterday










      • @YardenST From the bash manpage: "If the first character of parameter is an exclamation point (!), and parameter is not a nameref, it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion."
        – JoL
        yesterday












      • @YardenST In other words, bash takes #, expands it like it would $#, and then the result (let's say 5) is put through variable expansion again like it would $5.
        – JoL
        yesterday
















      to Kusalananda's answer.
      – Ljm Dullaart
      yesterday




      to Kusalananda's answer.
      – Ljm Dullaart
      yesterday












      Yes, you're right; I added it in the answer.
      – Ljm Dullaart
      yesterday




      Yes, you're right; I added it in the answer.
      – Ljm Dullaart
      yesterday












      can you please explain about this notation? ${!#}
      – YardenST
      yesterday




      can you please explain about this notation? ${!#}
      – YardenST
      yesterday












      @YardenST From the bash manpage: "If the first character of parameter is an exclamation point (!), and parameter is not a nameref, it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion."
      – JoL
      yesterday






      @YardenST From the bash manpage: "If the first character of parameter is an exclamation point (!), and parameter is not a nameref, it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion."
      – JoL
      yesterday














      @YardenST In other words, bash takes #, expands it like it would $#, and then the result (let's say 5) is put through variable expansion again like it would $5.
      – JoL
      yesterday




      @YardenST In other words, bash takes #, expands it like it would $#, and then the result (let's say 5) is put through variable expansion again like it would $5.
      – JoL
      yesterday












      up vote
      5
      down vote













      To get any argument from bash script, you can use slicing:



      #!/bin/bash

      # Get 3rd element from the end
      from_end1=3
      # Get last element
      from_end2=1

      # Get slice of array [end - from_end1 : end ] of length 1
      echo "${@: -$from_end1: 1}"
      echo "${@: -$from_end2: 1}"


      You can also use this to get Nth element:



      # Get 2nd element
      from_beginning=2

      echo "${@: $from_beginning: 1}"


      Remember to check for length; this might return your program's name or an empty string.






      share|improve this answer



















      • 1




        This is bash-specific, right? You should probably note that since the OP's question did not mention bash except in the #! (and in particular didn't use bash tag).
        – R..
        yesterday










      • @R.. Fair point, information added.
        – MatthewRock
        yesterday















      up vote
      5
      down vote













      To get any argument from bash script, you can use slicing:



      #!/bin/bash

      # Get 3rd element from the end
      from_end1=3
      # Get last element
      from_end2=1

      # Get slice of array [end - from_end1 : end ] of length 1
      echo "${@: -$from_end1: 1}"
      echo "${@: -$from_end2: 1}"


      You can also use this to get Nth element:



      # Get 2nd element
      from_beginning=2

      echo "${@: $from_beginning: 1}"


      Remember to check for length; this might return your program's name or an empty string.






      share|improve this answer



















      • 1




        This is bash-specific, right? You should probably note that since the OP's question did not mention bash except in the #! (and in particular didn't use bash tag).
        – R..
        yesterday










      • @R.. Fair point, information added.
        – MatthewRock
        yesterday













      up vote
      5
      down vote










      up vote
      5
      down vote









      To get any argument from bash script, you can use slicing:



      #!/bin/bash

      # Get 3rd element from the end
      from_end1=3
      # Get last element
      from_end2=1

      # Get slice of array [end - from_end1 : end ] of length 1
      echo "${@: -$from_end1: 1}"
      echo "${@: -$from_end2: 1}"


      You can also use this to get Nth element:



      # Get 2nd element
      from_beginning=2

      echo "${@: $from_beginning: 1}"


      Remember to check for length; this might return your program's name or an empty string.






      share|improve this answer














      To get any argument from bash script, you can use slicing:



      #!/bin/bash

      # Get 3rd element from the end
      from_end1=3
      # Get last element
      from_end2=1

      # Get slice of array [end - from_end1 : end ] of length 1
      echo "${@: -$from_end1: 1}"
      echo "${@: -$from_end2: 1}"


      You can also use this to get Nth element:



      # Get 2nd element
      from_beginning=2

      echo "${@: $from_beginning: 1}"


      Remember to check for length; this might return your program's name or an empty string.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited yesterday

























      answered yesterday









      MatthewRock

      3,87321847




      3,87321847








      • 1




        This is bash-specific, right? You should probably note that since the OP's question did not mention bash except in the #! (and in particular didn't use bash tag).
        – R..
        yesterday










      • @R.. Fair point, information added.
        – MatthewRock
        yesterday














      • 1




        This is bash-specific, right? You should probably note that since the OP's question did not mention bash except in the #! (and in particular didn't use bash tag).
        – R..
        yesterday










      • @R.. Fair point, information added.
        – MatthewRock
        yesterday








      1




      1




      This is bash-specific, right? You should probably note that since the OP's question did not mention bash except in the #! (and in particular didn't use bash tag).
      – R..
      yesterday




      This is bash-specific, right? You should probably note that since the OP's question did not mention bash except in the #! (and in particular didn't use bash tag).
      – R..
      yesterday












      @R.. Fair point, information added.
      – MatthewRock
      yesterday




      @R.. Fair point, information added.
      – MatthewRock
      yesterday










      up vote
      4
      down vote













      In bash (release 4.3+), you may assign the passed parameters to an array and access the last one by the index -1:



      #!/bin/bash

      params=( "$@" )
      printf 'The last parameter given to the script is %sn' "${params[-1]}"

      foo () {
      params=( "$@" )
      printf 'The last parameter given to the function is %sn' "${params[-1]}"
      }


      In general, negative indexes into arrays accesses the elements from the end of the array.






      share|improve this answer























      • A negative index might work on bash 4.2+ depending on the patch level. But an slice ${@: -1:1} works with negative indexes since bash 3.0.
        – Isaac
        yesterday










      • @Isaac That's good if you are code golfing, but not if you're writing code that others need to understand and maintain.
        – Kusalananda
        21 hours ago

















      up vote
      4
      down vote













      In bash (release 4.3+), you may assign the passed parameters to an array and access the last one by the index -1:



      #!/bin/bash

      params=( "$@" )
      printf 'The last parameter given to the script is %sn' "${params[-1]}"

      foo () {
      params=( "$@" )
      printf 'The last parameter given to the function is %sn' "${params[-1]}"
      }


      In general, negative indexes into arrays accesses the elements from the end of the array.






      share|improve this answer























      • A negative index might work on bash 4.2+ depending on the patch level. But an slice ${@: -1:1} works with negative indexes since bash 3.0.
        – Isaac
        yesterday










      • @Isaac That's good if you are code golfing, but not if you're writing code that others need to understand and maintain.
        – Kusalananda
        21 hours ago















      up vote
      4
      down vote










      up vote
      4
      down vote









      In bash (release 4.3+), you may assign the passed parameters to an array and access the last one by the index -1:



      #!/bin/bash

      params=( "$@" )
      printf 'The last parameter given to the script is %sn' "${params[-1]}"

      foo () {
      params=( "$@" )
      printf 'The last parameter given to the function is %sn' "${params[-1]}"
      }


      In general, negative indexes into arrays accesses the elements from the end of the array.






      share|improve this answer














      In bash (release 4.3+), you may assign the passed parameters to an array and access the last one by the index -1:



      #!/bin/bash

      params=( "$@" )
      printf 'The last parameter given to the script is %sn' "${params[-1]}"

      foo () {
      params=( "$@" )
      printf 'The last parameter given to the function is %sn' "${params[-1]}"
      }


      In general, negative indexes into arrays accesses the elements from the end of the array.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited yesterday

























      answered yesterday









      Kusalananda

      119k16223364




      119k16223364












      • A negative index might work on bash 4.2+ depending on the patch level. But an slice ${@: -1:1} works with negative indexes since bash 3.0.
        – Isaac
        yesterday










      • @Isaac That's good if you are code golfing, but not if you're writing code that others need to understand and maintain.
        – Kusalananda
        21 hours ago




















      • A negative index might work on bash 4.2+ depending on the patch level. But an slice ${@: -1:1} works with negative indexes since bash 3.0.
        – Isaac
        yesterday










      • @Isaac That's good if you are code golfing, but not if you're writing code that others need to understand and maintain.
        – Kusalananda
        21 hours ago


















      A negative index might work on bash 4.2+ depending on the patch level. But an slice ${@: -1:1} works with negative indexes since bash 3.0.
      – Isaac
      yesterday




      A negative index might work on bash 4.2+ depending on the patch level. But an slice ${@: -1:1} works with negative indexes since bash 3.0.
      – Isaac
      yesterday












      @Isaac That's good if you are code golfing, but not if you're writing code that others need to understand and maintain.
      – Kusalananda
      21 hours ago






      @Isaac That's good if you are code golfing, but not if you're writing code that others need to understand and maintain.
      – Kusalananda
      21 hours ago












      up vote
      3
      down vote













      Portable sh, not bash-specific, and without O(n) loops:



      eval x=$$(($#-1))


      The -1 yields the penultimate argument; replace it with the position you want relative to the end, or drop it entirely if you want the very last one.






      share|improve this answer



















      • 1




        One of the very few uses of eval I've ever seen that actually seems merited and safe.
        – Wildcard
        yesterday










      • @Isaac: Updated to note that. Thanks.
        – R..
        yesterday















      up vote
      3
      down vote













      Portable sh, not bash-specific, and without O(n) loops:



      eval x=$$(($#-1))


      The -1 yields the penultimate argument; replace it with the position you want relative to the end, or drop it entirely if you want the very last one.






      share|improve this answer



















      • 1




        One of the very few uses of eval I've ever seen that actually seems merited and safe.
        – Wildcard
        yesterday










      • @Isaac: Updated to note that. Thanks.
        – R..
        yesterday













      up vote
      3
      down vote










      up vote
      3
      down vote









      Portable sh, not bash-specific, and without O(n) loops:



      eval x=$$(($#-1))


      The -1 yields the penultimate argument; replace it with the position you want relative to the end, or drop it entirely if you want the very last one.






      share|improve this answer














      Portable sh, not bash-specific, and without O(n) loops:



      eval x=$$(($#-1))


      The -1 yields the penultimate argument; replace it with the position you want relative to the end, or drop it entirely if you want the very last one.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited yesterday

























      answered yesterday









      R..

      1,85611014




      1,85611014








      • 1




        One of the very few uses of eval I've ever seen that actually seems merited and safe.
        – Wildcard
        yesterday










      • @Isaac: Updated to note that. Thanks.
        – R..
        yesterday














      • 1




        One of the very few uses of eval I've ever seen that actually seems merited and safe.
        – Wildcard
        yesterday










      • @Isaac: Updated to note that. Thanks.
        – R..
        yesterday








      1




      1




      One of the very few uses of eval I've ever seen that actually seems merited and safe.
      – Wildcard
      yesterday




      One of the very few uses of eval I've ever seen that actually seems merited and safe.
      – Wildcard
      yesterday












      @Isaac: Updated to note that. Thanks.
      – R..
      yesterday




      @Isaac: Updated to note that. Thanks.
      – R..
      yesterday










      up vote
      0
      down vote













      In zsh, the most natural thing, I think, would be:



      echo "ultimate: ${@[$#]}"
      echo "ultimate: ${@[-1]}"
      echo "penultimate: ${@[-2]}"
      echo "penultimate: ${@[$(($# - 1))]}"





      share|improve this answer

























        up vote
        0
        down vote













        In zsh, the most natural thing, I think, would be:



        echo "ultimate: ${@[$#]}"
        echo "ultimate: ${@[-1]}"
        echo "penultimate: ${@[-2]}"
        echo "penultimate: ${@[$(($# - 1))]}"





        share|improve this answer























          up vote
          0
          down vote










          up vote
          0
          down vote









          In zsh, the most natural thing, I think, would be:



          echo "ultimate: ${@[$#]}"
          echo "ultimate: ${@[-1]}"
          echo "penultimate: ${@[-2]}"
          echo "penultimate: ${@[$(($# - 1))]}"





          share|improve this answer












          In zsh, the most natural thing, I think, would be:



          echo "ultimate: ${@[$#]}"
          echo "ultimate: ${@[-1]}"
          echo "penultimate: ${@[-2]}"
          echo "penultimate: ${@[$(($# - 1))]}"






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered yesterday









          JoL

          81039




          81039






















              up vote
              0
              down vote













              The clasic solutions for POSIX shells (which also work on ksh, zsh or bash) are:



               for last do :;done; echo "last=$last"
              eval "last=$$#"; echo "last=$last"


              For newer shells (ksh93,zsh,bash):



               echo "last=${@: -1}"
              echo "last=${@:(-1)}"
              echo "last=${@:~0}"
              echo "last=${@:$#}"


              Only for:



              bash echo "last=${!#}"
              bash echo "last=$BASH_ARGV"
              zsh echo "last=${@[-1]}"
              zsh echo "last=${@[#]}"



              For the penultimate argument:



               for arg do penultimate=$ultimate; ultimate=$arg; done; echo "$penultimate"
              eval penultimate=$$((#-1))
              echo "${@:$((#-1)):1}"
              echo "${@: -2:1}"
              echo "${@:~1:1}"





              share|improve this answer

























                up vote
                0
                down vote













                The clasic solutions for POSIX shells (which also work on ksh, zsh or bash) are:



                 for last do :;done; echo "last=$last"
                eval "last=$$#"; echo "last=$last"


                For newer shells (ksh93,zsh,bash):



                 echo "last=${@: -1}"
                echo "last=${@:(-1)}"
                echo "last=${@:~0}"
                echo "last=${@:$#}"


                Only for:



                bash echo "last=${!#}"
                bash echo "last=$BASH_ARGV"
                zsh echo "last=${@[-1]}"
                zsh echo "last=${@[#]}"



                For the penultimate argument:



                 for arg do penultimate=$ultimate; ultimate=$arg; done; echo "$penultimate"
                eval penultimate=$$((#-1))
                echo "${@:$((#-1)):1}"
                echo "${@: -2:1}"
                echo "${@:~1:1}"





                share|improve this answer























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  The clasic solutions for POSIX shells (which also work on ksh, zsh or bash) are:



                   for last do :;done; echo "last=$last"
                  eval "last=$$#"; echo "last=$last"


                  For newer shells (ksh93,zsh,bash):



                   echo "last=${@: -1}"
                  echo "last=${@:(-1)}"
                  echo "last=${@:~0}"
                  echo "last=${@:$#}"


                  Only for:



                  bash echo "last=${!#}"
                  bash echo "last=$BASH_ARGV"
                  zsh echo "last=${@[-1]}"
                  zsh echo "last=${@[#]}"



                  For the penultimate argument:



                   for arg do penultimate=$ultimate; ultimate=$arg; done; echo "$penultimate"
                  eval penultimate=$$((#-1))
                  echo "${@:$((#-1)):1}"
                  echo "${@: -2:1}"
                  echo "${@:~1:1}"





                  share|improve this answer












                  The clasic solutions for POSIX shells (which also work on ksh, zsh or bash) are:



                   for last do :;done; echo "last=$last"
                  eval "last=$$#"; echo "last=$last"


                  For newer shells (ksh93,zsh,bash):



                   echo "last=${@: -1}"
                  echo "last=${@:(-1)}"
                  echo "last=${@:~0}"
                  echo "last=${@:$#}"


                  Only for:



                  bash echo "last=${!#}"
                  bash echo "last=$BASH_ARGV"
                  zsh echo "last=${@[-1]}"
                  zsh echo "last=${@[#]}"



                  For the penultimate argument:



                   for arg do penultimate=$ultimate; ultimate=$arg; done; echo "$penultimate"
                  eval penultimate=$$((#-1))
                  echo "${@:$((#-1)):1}"
                  echo "${@: -2:1}"
                  echo "${@:~1:1}"






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered yesterday









                  Isaac

                  10.7k11447




                  10.7k11447















                      Popular posts from this blog

                      Quarter-circle Tiles

                      build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

                      Mont Emei