我有一个jobscount()
功能:
jobscount() {
local stopped='$(jobs -s | wc -l | tr -d " ")'
local running='$(jobs -r | wc -l | tr -d " ")'
echo -n "${running}r/${stopped}s"
}
我在我的中使用这个函数$PS1
:
PS1=" \w $(jobscount) \$ "
唯一的问题是,如果没有后台进程运行或没有停止的作业,则该函数无用地占用$PS1
空间。我想要的是如果 或stopped
值running
大于0
,只有那时它出现了。
答案1
你们把这种方式搞得太复杂了。只需检查输出是否jobs
非空,然后添加\j
到您的 PS1 字符串。
if [ -n "$(jobs -p)" ]; then echo "\j"; fi
这是我的提示中的一个片段:
#Show number of jobs if at least one job
export PS1+='`if [ -n "$(jobs -p)" ]; then echo "(\j)"; fi`'
答案2
首先,我建议修正你的引用。从命令提示符独立运行时,当前函数不会输出有用的数据。
然后添加一个条件,使用OR 列表分隔符, 之前echo
:
jobscount() {
local stopped=$(jobs -sp | wc -l)
local running=$(jobs -rp | wc -l)
((running+stopped)) && echo -n "${running}r/${stopped}s "
}
PS1=' \w $(jobscount)\$ '
我还建议添加-p
到jobs
调用中,以便它们仅输出进程 PID。否则,yes $'foo\nbar' &
在 2 行上列出的命令将被计数两次。
答案3
由于您在每次提示时都运行此命令,因此值得节省一些外部调用。
要仅在有后台作业时显示计数,请检查数字,如果它们全为 0,则不要打印任何内容。
运行jobs -p
仅获取进程 ID,更容易可靠地解析。
jobscount() {
set -- $(jobs -rp)
set $# $(jobs -sp)
set $1 $(($#-1))
if [ $1 -ne 0 ] || [ $2 -ne 0 ]; then echo "${1}r/${2}s"; fi
}
PS1=' \w $(jobscount) \$ '
顺便说一句,在分配给 时请注意右侧的引号PS1
。使用双引号,当您设置变量时会调用该函数。您需要使用单引号,以便 的值PS1
包含文本$(jobscount)
,并且每次显示提示时都会调用该函数。
您可以通过PROMPT_COMMAND
设置变量而不是使用函数的输出来保存一个分叉。
set_jobscount () {
set $(jobs -rp)
set $# $(jobs -sp)
set $1 $(($#-1))
if [ $1 -ne 0 ] || [ $2 -ne 0 ]; then
jobscount="${1}r/${2}s"
else
jobscount=
fi
}
PROMPT_COMMAND="$PROMPT_COMMAND
set_jobscount"
PS1=' \w ${jobscount} \$ '
和往常一样,zsh 更简单(虽然看起来很神秘)。
precmd () {
jobscount=${(M)#${jobstates%%:*}:#running}r/${(M)#${jobstates%%:*}:#suspended}s
if [[ $jobscount == r0/s0 ]]; then jobscount=; fi
}
setopt prompt_subst
PS1='… ${jobscount} …'
这里jobstates
Zsh 提供的变量来自zsh/parameter
模块。#running
并将#suspended
输出分开以仅包括正在运行或挂起的作业。(M)
标志并%%
来自参数扩展。(M)
flag 删除不匹配的元素并%%
删除:
输出中之后的任何内容$jobstates
答案4
PS1 中的 $() 怎么样,例如:
export PS1='\w $(if test "\j" -ne "0"; then echo -e "\033[32m\j "; fi )\[\033[01;35m\]\$\[\033[00m\] '