Skip to content

Instantly share code, notes, and snippets.

@githubhjs
Last active September 3, 2025 09:45
Show Gist options
  • Select an option

  • Save githubhjs/56c97d7107715314fb85abfff9870fec to your computer and use it in GitHub Desktop.

Select an option

Save githubhjs/56c97d7107715314fb85abfff9870fec to your computer and use it in GitHub Desktop.
This Zsh function, dedup_env_var, is designed to remove duplicate entries from a colon-separated environment variable, such as $PATH.
#!/bin/zsh
#
# Function: Removes duplicate, colon-separated entries from a specified
# environment variable.
# Usage: dedup_env_var <VARIABLE_NAME>
# Example: dedup_env_var PATH
#
dedup_env_var () {
# Store the first argument (the environment variable's name) in a local variable.
local var_name="$1"
# Check if the target environment variable is unset or empty.
# (P)var_name is Zsh's parameter indirection, which gets the value of the
# variable whose name is stored in the var_name variable.
if [ -z "${(P)var_name}" ]; then
# Print the error message to standard error (stderr).
echo "Error: Environment variable '$var_name' is not set." >&2
return 1
fi
# Declare a local (-a for array) array with unique (-U) elements.
# This is a more explicit way of writing 'typeset -U array'.
local -aU array
# This is the updated, robust line:
# 1. `${(P)var_name}`: Gets the content of the environment variable (e.g., the value of $PATH).
# 2. `(@s/:/)`: Splits the string by colons. The `@` flag ensures proper array
# treatment and preserves empty fields.
# 3. `("...")`: The outer double quotes prevent word splitting, ensuring that
# paths with spaces are treated as a single, complete element.
# 4. Because 'array' was declared as unique (-U), duplicates are automatically
# removed during this assignment.
array=("${(@s/:/)${(P)var_name}}")
# `(j/:/)` joins the array elements back into a single string, separated by colons.
# Finally, export the cleaned-up string, overwriting the original environment variable.
export "$var_name"="${(j/:/)array}"
}
@githubhjs
Copy link
Author

好的,這張圖片展示了一個名為 dedup_env_var 的 Zsh function 以及它的使用範例。

這個 function 的主要功能是移除指定環境變數中,以冒號 (:) 分隔的路徑/值中的重複項目。

這對於清理像 $PATH 或 $LD_LIBRARY_PATH 這樣可能因多次 source 設定檔而累積了重複路徑的環境變數非常有用。

功能逐行分析
讓我們來逐行解析這個 function 的程式碼:

Bash

dedup_env_var () {
# 宣告一個名為 var_name 的本地變數,其值為傳入 function 的第一個參數。
# 例如,如果執行 dedup_env_var PATH,那麼 var_name 的值就是 "PATH"。
local var_name="$1"

# 宣告一個本地陣列變數 array。
local array

# 檢查指定的環境變數是否為空或未設定。
# (P)var_name 是 Zsh 的特殊語法,稱為「參數間接取值」。
# 它會先取得 var_name 的值 (例如 "PATH"),然後再取得該名稱的變數值 (即 $PATH 的內容)。
# [ -z "..." ] 檢查字串是否為空。
if [ -z "${(P)var_name}" ]
then
    # 如果變數是空的,就印出錯誤訊息並返回失敗狀態碼 1。
    echo "Environment variable '$var_name' is not set."
    return 1
fi

# 這是最關鍵的一行。
# typeset -U array 宣告 array 是一個「唯一值」陣列。
# 任何重複的元素在加入此陣列時會被自動忽略。
typeset -U array

# 這行做了兩件事:
# 1. ${(s/:/)Pvar_name}: 這會取得 $var_name 所指向的變數內容 (例如 $PATH),
#    並使用冒號 (:) 作為分隔符,將其分割成一個陣列。
# 2. array=(...): 將分割後的陣列元素賦值給 array。
#    因為 array 被宣告為 -U (unique),所以在這個賦值過程中,重複的路徑就會被自動濾除。
array=(${(s/:/)Pvar_name})

# 將清理過的陣列重新組合並導出。
# 1. ${(j/:/)array}: 這會將 array 陣列中的所有元素用冒號 (:) 連接成一個單一的字串。
# 2. export "$var_name"=...: 使用參數間接賦值的方式,將重組後的乾淨字串
#    賦值回原來的環境變數 (例如 PATH),並使用 export 將其設為環境變數。
export "$var_name"="${(j/:/)array}"

}
圖片中的指令流程
which dedup_env_var: 使用者執行 which 指令來查看 dedup_env_var 這個指令的定義。因為它是一個 shell function,所以 shell 直接印出了它的原始碼。

dedup_env_var PATH: 使用者呼叫了這個 function,並傳入 PATH 作為參數。

function 內部會讀取當前的 $PATH 環境變數。

將 $PATH 的值(例如 /usr/local/bin:/usr/bin:/bin:/usr/local/bin)按冒號分割。

利用 typeset -U 的特性,移除重複的項目(/usr/local/bin)。

將處理後不重複的路徑重新用冒號組合成一個新字串(/usr/local/bin:/usr/bin:/bin)。

最後,將這個乾淨的字串重新 export 成新的 $PATH 環境變數。

總結
總而言之,dedup_env_var 是一個非常實用的 Zsh 工具函式,它利用了 Zsh 強大的參數擴展 (Parameter Expansion) 和陣列特性,以一種高效且簡潔的方式來清理和整理環境變數中重複的路徑。

@githubhjs
Copy link
Author

Of course. Here is an explanation of the Zsh function in English.

This Zsh function, dedup_env_var, is designed to remove duplicate entries from a colon-separated environment variable, such as $PATH.

It's a useful utility for cleaning up variables that may have accumulated redundant paths after sourcing multiple configuration files.

Line-by-Line Code Analysis
Here is a breakdown of what each line in the function does:

Bash

dedup_env_var () {
# Declares a local variable 'var_name' and assigns it the value of the
# first argument passed to the function.
# For example, if you run dedup_env_var PATH, then $var_name becomes "PATH".
local var_name="$1"

# Declares a local array variable named 'array'.
local array

# This 'if' block checks if the target environment variable is empty or not set.
# `${(P)var_name}` is a Zsh-specific feature called "parameter indirection".
# It takes the value of var_name (e.g., "PATH") and uses it as the name of
# another variable to expand (effectively becoming $PATH).
# `[ -z "..." ]` tests if the resulting string is empty.
if [ -z "${(P)var_name}" ]
then
    # If the variable is empty, it prints an error and exits with a non-zero status.
    echo "Environment variable '$var_name' is not set."
    return 1
fi

# This is the core of the de-duplication logic.
# `typeset -U array` declares 'array' as an array that holds only unique elements.
# Any duplicate values assigned to it will be automatically discarded.
typeset -U array

# This line populates the array.
# 1. `(P)var_name`: Gets the value of the environment variable (e.g., the content of $PATH).
# 2. `(s/:/)`: This is a Zsh expansion flag that splits the string by a delimiter,
#    in this case, the colon ':', creating an array of paths.
# 3. `array=(...)`: The resulting array of paths is assigned to the `array` variable.
#    Because `array` was declared as unique (`-U`), this step automatically removes all duplicates.
array=(${(s/:/)Pvar_name})

# This line rebuilds the environment variable from the cleaned-up array.
# 1. `${(j/:/)array}`: This joins the elements of the `array` back into a single
#    string, using a colon ':' as the separator between them.
# 2. `export "$var_name"=...`: Using parameter indirection again, it assigns the
#    newly joined, de-duplicated string back to the original environment variable
#    (e.g., `PATH=...`) and exports it, making it available to subprocesses.
export "$var_name"="${(j/:/)array}"

}
Explanation of the Commands in the Screenshot
which dedup_env_var: The user runs which to find the location of the dedup_env_var command. Since it is a shell function and not an executable file in the system's PATH, the shell responds by printing the function's source code.

dedup_env_var PATH: The user then calls the function, passing PATH as the argument. This triggers the function to:

Read the current value of the $PATH environment variable.

Split it into an array, removing any duplicate path entries in the process.

Join the unique paths back together into a single, colon-delimited string.

Export the cleaned-up string as the new value for the $PATH variable.

Summary
In essence, dedup_env_var is an elegant and efficient Zsh script that leverages Zsh's advanced parameter expansion and unique array features to clean up environment variables.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment