Bash提示缩短

Bash提示缩短,bash,.bash-profile,Bash,.bash Profile,我刚从tcsh移动到bash,我特别错过了使用%c02(同时设置了省略号)的目录缩短提示选项 我看到PROMPT\u DIRTRIM几乎做了正确的事情(我认为省略号除外),但我只在bash3(在OSX上)。我发现,它缩短了总长度,因此打破了目录中间的路径名,这是我不喜欢的。< /P> 所以我想到了这个: PROMPT_DIRTRIM=2 ## from bash4, but used here dirtrim() { local NAME="$1" start= endelts=

我刚从
tcsh
移动到
bash
,我特别错过了使用
%c02
(同时设置了
省略号
)的目录缩短提示选项

我看到
PROMPT\u DIRTRIM
几乎做了正确的事情(我认为省略号除外),但我只在
bash
3(在OSX上)。我发现,它缩短了总长度,因此打破了目录中间的路径名,这是我不喜欢的。< /P> 所以我想到了这个:

PROMPT_DIRTRIM=2   ## from bash4, but used here
dirtrim() 
{
    local NAME="$1" start= endelts=
    [[ "$NAME" =~ ^"$HOME"(/|$) ]] && NAME="~${NAME#$HOME}"  ## $HOME ==> ~
    IFS=/ read -ra elts <<< "$NAME";          ## split $PWD on "/"
    start=$((${#elts[@]}-${PROMPT_DIRTRIM}))  ## first element to retain
    if [ ${start} -gt 1 ]; then     
        for ((i=${start}; i<${#elts[@]}; i++)); do 
            endelts="${endelts}/${elts[$i]}"; ## concat together the trailing path
        done
        NAME="...${endelts}"
    fi
    echo "$NAME"    
}
PS1='\h:$(dirtrim "$PWD")\$ '
但是我对
bash
还比较陌生,对(())循环的显式
不满意;但是,我似乎找不到任何其他方法以正确处理目录名称中的空格的方式(例如,使用
${elts[@]:${start}}
)重新加入拆分的
elts
数组的最后条目。有什么提示可以这样做或其他改进吗

(顺便说一句,我认为这是一个编程问题,
bash
是一种编程语言……)

您可以尝试以下方法:

if ((start > 1)); then
  name=$(IFS=/; echo .../"${elts[*]:start}")
  # If your terminal is correctly set up for unicode, you can save two character positions:
  # name=$(IFS=/; echo …/"${elts[*]:start}")
fi
注意,在bash中,在算术上下文中,包括
(…)
的内部和数组下标,您可以只写变量的名称;不需要信号

另一种方法是

if ((start > 1)); then
  printf -v name "/%s" "${elts[@]:start}"
  name=...$name
fi
另一种解决方案是在
BASH\u REMATCH
数组中使用正则表达式捕获,而不是拆分和重新连接字符串:

dirtrim () { 
  local path="$1";
  [[ $path =~ ^"$HOME"(/.*)? ]] && path=~${BASH_REMATCH[1]};
  ((PROMPT_DIRTRIM)) &&
    [[ $path =~ ...*((/[^/]*){$PROMPT_DIRTRIM}) ]] &&
    path=…${BASH_REMATCH[1]};
  echo "$path"
}

((PROMPT_DIRTRIM))
测试不是完全健壮的,因为在算术上下文中bash计算的特性。对于发行版,您可能更喜欢像
[[$PROMPT\u DIRTRIM=~^[1-9][0-9]*$]]
这样的东西,但这不是一个真正的答案,但您可能想看看
mksh
是如何实现这一点的:

PS1=${| local e=$? (( e )) && REPLY+="$e|" REPLY+=${USER:=$(ulimit -c 0; id -un 2>/dev/null || echo \?)} REPLY+=@${HOSTNAME%%.*}: local d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || d=${d/#$p/~} local m=${%d} n p=...; (( m > 0 )) || m=${#d} (( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || p= REPLY+=$p$d return $e }
(e)及及答答覆+上述人士的答答覆+上述人士的答覆+上述人士的答覆+上述人士的用户::{{用户:{用户:{用户:$(ulMIMIMIT-c 0;id-UN2-2>/dev/发展/发展/null |;;回声回声回声回声????;上述上述上述人士人士的PS1.PS1.PS1.PS1.PS1.PS1.PS1.0;PS1.PS1.PS1.PS1.PS1.0;PS1.PS1.PS1.PS1.0;PS1.PS1.0;及及及及上述上述上述上述上述上述上述上述上述上述上述人士的发展//发展/发展/发展/发展/发展/及及及及及及回声\\124;回声回声;回声;回声;回声;回声;回声;回声;回声;回声;回声;回声??????????3<7?7:COLUMNS/3))&&d=${d:(-n)}| | p=REPLY+=$p$d return$e}
不幸的是,我相信它使用了一些不在
bash
中的扩展

麻生太郎,既然你在换炮弹。。。你考虑过吗


它是开箱即用的,然后是一些。

1。就套管达成一致意见;我从中得到了
姓名。2.我的意思是
((start>1))
——如果
start==1
您只保留第一个条目;3.我想你的意思是
name=$(IFS=/;echo…/“${elts[*]:start}”)
(注意
IFS=/
和missing
$
)@andrew:bash数组的第一个条目具有索引0。你说得对,我打字的时候正冲出门外。很抱歉,我现在已经修复了。是的,但是第0个条目是“~”或null,因此我们确实希望只在
start>1
@AndrewJaffe:啊,说得好。如果不缩短,就没有理由缩短。为了您的观看乐趣,我添加了一个使用regex的解决方案,它避免了拆分和联接。Bash是一种编程语言。@Jonathan Leffler:同意——这是对两次投票结束的回应!我肯定关于Bash编程的问题是编程问题,因此是关于堆栈溢出的主题。关于shell编程的结束性问题作为一个离题问题曾经是一个主要问题;这些天来,我看不到它发生的太多,但这可能只是意味着我错过了它,它一直在发生。FWIW:我也不喜欢长提示:我根本不在提示中包含路径。在“sphinx”机器上,我的提示是
sphinx JL:
。使用Mac终端,您可以在终端标题栏(属性->窗口和查找标题部分)中找到路径。
PS1=${| local e=$? (( e )) && REPLY+="$e|" REPLY+=${USER:=$(ulimit -c 0; id -un 2>/dev/null || echo \?)} REPLY+=@${HOSTNAME%%.*}: local d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || d=${d/#$p/~} local m=${%d} n p=...; (( m > 0 )) || m=${#d} (( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || p= REPLY+=$p$d return $e }