Search code examples
functionshellscriptingzsh

Retrieving input argument at index via alias in zsh


I am trying to create functions and aliases in ZSH that make parameters handling easier to read.

As such, I wanted to create things like the example below:

#!/bin/zsh
myCustomFunction(){
  local numberOfParameters=$(count-parameters)
  local lastParameter=$(get-parameter $numberOfParameters)
  echo "Number of parameters: $numberOfParameters"
  echo "Last parameter is: $lastParameter"
}

Where count-parameters is defined below:

#!/bin/zsh
alias count-parameters='echo "$#"

How would I be able to implement get-parameter? I have been trying with "$@", as suggested in here, but that does not seem to work.

My desired result is that given an input such as:

myCustomFunction.sh "First param" "Second param" "Third param"

The output would be:

Number of parameters: 3
Last parameter: Third param

Solution

  • Through trial and error, I was able to accomplish the desired result.

    Here's how I did it.

    1. Count parameters alias
    #!/bin/zsh
    alias count-parameters='echo "$#"'
    

    For get-parameter, I had to perform multiple operations (hacky way but it works)

    • Save each parameter in a file (each parameter separated by the NUL character)
    • Store the text within the file in a variable and loop over each character. Use the NUL character to determine where one parameter finishes and the next begins. Then, remove the file that was temporarily created
    #!/bin/zsh
    export tempParameterFile="$HOME/.params.txt"
    alias save-parameters='save_parameters "$@"'
    
    #!/bin/zsh
    save_parameters(){
      numberOfParams=${#}
      if [ "$numberOfParams" -gt 0 ]; then
        rm -f "$tempParameterFile"
        while (( $# ))
        do
          echo -n "$1" >> "$tempParameterFile"
          echo -ne $'\0' >> "$tempParameterFile" # Adding NUL character after each parameter
          shift
        done
      fi
    }
    
    #!/bin/zsh
    
    get_parameter(){
      local indexToUse=$1
      #echo "Called get_parameter for index $1"
      local currentIndex=0
      local nullCharacter=$'\0'
      local currentParam=""
      local allParameters=$(cat "$tempParameterFile")
      local currentCharacter=""
      for (( index=0; index<${#allParameters}; index++ ));
      do
        currentCharacter="${allParameters:$index:1}"
        if [ "$currentCharacter" = "$nullCharacter" ]; then # When the null character is found
          if [ "$currentIndex" = "$indexToUse" ];then # If the current index matches the desired index
            echo "$currentParam" # We found the word we were looking for
            return 0
          else # If the current index is lower than the desired index
            currentIndex=$(( $currentIndex + 1 )) # We increase the current index
            currentParam="" # And reset the current parameter
          fi
        else # If the character read is not  the null character
          currentParam="$currentParam$currentCharacter" # We append the character to the current param
        fi
      done
    }
    
    #!/bin/zsh
    alias get-parameter='save_parameters "$@" && get_parameter'
    

    When running the command:

    ╰─$ myCustomFunction.sh "One param" "Second param" "Third param" "Fourth param"
    Number of parameters: 4
    Last parameter: Fourth param
    

    The desired result is achieved.

    EDIT: Updated code to address the possibility of an input parameter having a new line in it. Now using, as suggested in the comments, the NUL character to differentiate between parameters.