如何提高此代码中 PS1 的生成速度?

How to improve generation speed of PS1 in this code?

PROMPT_COMAND 运行 慢。需要优化代码。

我使用 bash 内置 PROMPT_COMMAND 来自定义 PS1。执行了太多 echo | grep 命令以获取彩色 git 分支 indication.The 提示 运行 慢得多。关于优化有什么想法吗?

function git_branch {                                                            
    branch="`git branch 2>/dev/null | grep "^\*" | sed -e "s/^\*\ //"`"          
    if [ "${branch}" != "" ];then                                                
        if [ "${branch}" = "(no branch)" ];then                                  
            branch="(`git rev-parse --short HEAD`...)"                           
        fi                                                                       
        echo "$branch"                                                           
    fi                                                                           
}                                                                                

# display last two dentry                                                        
function get_curdir {                                                            
    dir=$(pwd);                                                                  
    last_dirent=${dir##*/}                                                       
    dir=${dir%/*}                                                                
    lastbutone_dirent=${dir##*/}                                                 
    echo -n "${lastbutone_dirent}/${last_dirent}"                                
}                                                                                

# colours                                                                        
RED="\[3[1;31m\]"                                                             
GREEN="\[3[1;32m\]"                                                           
BROWN="\[3[0;33m\]"                                                           
BLUE="\[3[1;34m\]"                                                            
PURPLE="\[3[1;35m\]"                                                          
CYAN="\[3[1;36m\]"                                                            
GRAY="\[3[0;37m\]"                                                            
LIGHT_RED="\[3[0;31m\]"                                                       
LIGHT_GREEN="\[3[1;32m\]"                                                                                                                                                
LIGHT_BLUE="\[3[0;34m\]"                                                      
YELLOW="\[3[1;33m\]"                                                          
LIGHT_PURPLE="\[3[1;35m\]"                                                    
LIGHT_CYAN="\[3[1;36m\]"                                                      
LIGHT_GRAY="\[3[0;37m\]"                                                      
WHITE="\[3[1;37m\]"                                                           
RESTORE="\[3[0m\]" #0m restores to the terminal's default colour

function prompt_command {                                                        
    RET=$?                                                                       
    PS1="${CYAN}[${RESTORE}${GREEN}\u${RESTORE} "                                
    PS1+="${BLUE}$(get_curdir)${RESTORE}${CYAN}]${RESTORE}"                      

    BRANCH=$(git_branch)                                                         
    if [ "${BRANCH}" != "" ]; then                                               
        STATUS="$(git status -s 2>/dev/null)"                                    
        if echo "${STATUS}" | grep -e "??"; then                                 
            PARENTHESES_COLOR=${RED}                                             
        else                                                                     
            PARENTHESES_COLOR=${GREEN}                                           
        fi >/dev/null                                                            
        if [ "${STATUS}" = "" ]; then                                            
            BRANCH_COLOR=${GREEN}                                                
        else                                                                     
            if echo "${STATUS}" | grep -e "^[ M]M"; then                         
                if echo "${STATUS}" | grep -e "^M[ M]"; then                     
                    BRANCH_COLOR=${PURPLE}                                       
                else                                                             
                    BRANCH_COLOR=${RED}                                          
                fi                                                               
            elif echo "${STATUS}" | grep -e "^M "; then                          
                BRANCH_COLOR=${YELLOW}                                           
            fi                                                                   
        fi >/dev/null                                                            
        PS1+="${PARENTHESES_COLOR}(${RESTORE}${BRANCH_COLOR}$(git_branch)${RESTORE}${PARENTHESES_COLOR})${RESTORE}"                                                         
    fi                                                                           

    if [ "$RET" = "0" ]; then                                                    
        PS1+=" ${CYAN}->${RESTORE} "                                             
    else                                                                         
        PS1+=" ${RED}->${RESTORE} "                                              
    fi                                                                           
}                                                                                
export PROMPT_COMMAND=prompt_command

更新

我 运行 在 git 存储库所在的某个目录中进行简单测试,并使用 time 获取时间成本。

for ((i=0;i<10000;i++));do                                                       
    prompt_command;                                                              
done

以上原版性能为:

real    3m4.567s
user    1m32.698s
sys     3m2.495s

然后我将 [] 更改为 [[ ]],diff 如下所示:

17,18c17,18
<     if [ "${branch}" != "" ];then
<               if [ "${branch}" = "(no branch)" ];then
---
>     if [[ "${branch}" != "" ]];then
>               if [[ "${branch}" == "(no branch)" ]];then
58c58
<       if [ "${BRANCH}" != "" ]; then
---
>       if [[ "${BRANCH}" != "" ]]; then
65c65
<               if [ "${STATUS}" = "" ]; then
---
>               if [[ "${STATUS}" == "" ]]; then
81c81
<       if [ "$RET" = "0" ]; then
---
>       if [[ "$RET" == "0" ]]; then

性能稍差

real    3m7.690s
user    1m30.717s
sys     3m6.676s

所以,[] 没关系。 但是内置的正则表达式有很大帮助。 当我更改为以下内容并将 $(pwd) 替换为 $PWD

    if [ "${BRANCH}" != "" ]; then                                                  
        regex_untracked=".*^\?\?.*"                                                 
        regex_staged=".*^M[ M].*"                                                   
        regex_modified=".*^[ M]M.*"                                                 
        STATUS="$(git status -s 2>/dev/null)"                                       
        if [[ ${STATUS} =~ $regex_untracked ]]; then                                
            PARENTHESES_COLOR=${RED}                                                
        else                                                                        
            PARENTHESES_COLOR=${GREEN}                                              
        fi >/dev/null                                                               
        if [[ ${STATUS} =~ $regex_modified ]]; then                                 
            if [[ ${STATUS} =~ $regex_staged ]]; then                               
                BRANCH_COLOR=${PURPLE}                                              
            else                                                                    
                BRANCH_COLOR=${RED}                                                 
            fi                                                                      
        elif [[ ${STATUS} =~ $regex_staged ]]; then                                 
            BRANCH_COLOR=${YELLOW}                                                  
        else                                                                        
            BRANCH_COLOR=${GREEN}                                                                                                                                           
        fi >/dev/null                                                               
        PS1+="${PARENTHESES_COLOR}(${RESTORE}${BRANCH_COLOR}$(git_branch)${RESTORE}${PARENTHESES_COLOR})${RESTORE}"
    fi

消耗时间减少:

real    2m15.534s
user    1m1.036s
sys     2m15.043s

顺便说一下,如果没有这个彩色分支功能,性能是

real    1m0.478s
user    0m29.499s
sys     1m1.411s

bash有自己的built-in正则表达式匹配。例如,替换

echo "${STATUS}" | grep -e "^[ M]M"

regex="^[ M]M"
[[ $STATUS =~ $regex ]]