如何在Bash中控制作业的“名称”?

时间:2008-12-23 17:14:18

标签: bash

我正试图控制我的xterm窗口的标题,我的聪明才智最终超过了我的知识。 : - )

我有三个功能:一个设置窗口的标题;一个接受传递命令,调用标题函数,并执行命令;并且在使用jobs确定标题后恢复工作:

title () {
    echo -en "\e]1;$(hostname) : $1\a\e]2;$(hostname) : $2\a"
}

run () {
    title $(basename $1) "$*";
    $*
}

fg () {
    if [[ "x" == "x$1" ]]; then
        title $(jobs | awk '/\['$1'\]/{print $3}') "$(jobs | awk -F '  +' '/\[[0-9]\]\+/{print $3}')";
    else
        title $(jobs | awk '/\['$1'\]/{print $3}') "$(jobs | awk -F '  +' '/\['$1'\]/{print $3}')";
    fi;
    builtin fg $*
}

现在,所有这一切都工作得非常好......主要是。通过手动调用函数来设置标题可以正常工作。通过run函数设置标题可以正常工作。通过恢复作业来设置标题工作正常......除非使用run函数启动作业:

$ nano foo.txt
<CTRL-Z>
$ run nano bar.txt
<CTRL-Z>
$ jobs
[1]-  Stopped                 nano foo.txt
[2]+  Stopped                 $*

好吧,我认为,从技术上讲,是run函数正在执行的命令的名称,但在这种情况下,这并不是一件有用的事情。

所以,因为我不仅达到了远远超过我对Bash知识的限制,也许这里有人可以帮我解决这个问题。 : - )

2 个答案:

答案 0 :(得分:0)

嗯,这不太理想,但我想出了一个至少正确设置我的标题的解决方案:

fg () {
    if [[ "x" == "x$1" ]]; then
        _CMD=$(ps -o cmd --no-headers $(jobs -l | awk '/\[[0-9]\]\+/{print $2}'));
    else
        _CMD=$(ps -o cmd --no-headers $(jobs -l | awk '/\['$1'\]/{print $2}'));
    fi;
    title $(basename $(echo $_CMD | awk '{print $1}')) "$_CMD";
    unset _CMD;
    builtin fg $*;
}

这使用jobs' - l选项获取进程ID,然后使用ps找到它,其中列出了正确的命令。不幸的是,ps似乎很慢,在恢复时会造成明显的延迟(〜1/4秒)。

答案 1 :(得分:0)

男人bash说:

  

fg [jobspec]       在前台恢复jobspec,并使其成为当前作业。       如果jobspec不存在,那么shell的当前作业的概念       使用。

关于当前的工作&#39;:

  

符号%%和       %+指的是shell对当前作业的概念,这是最后一个       当工作在前台或在后台启动时停止工作。

这是你真正想做的事情;模仿fg命令正在做什么。

这里的大多数其他技巧都在参数扩展中详细说明。

myfg() { # just so I know what I'm invoking while testing
    local cmdline
    cmdline=$(jobs -l "${1:-%%}") || return # bail if jobs failed
    cmdline=${cmdline:30} # Extract the part we want
    title "${cmdline%% *}" "${cmdline}"

    builtin fg "$jobspec"
}

对于您的运行命令,在许多情况下,eval命令将执行您的操作 想:

eval "$@"

但是用单引号来装备每个单词以防止它是很好的 重估它:

eval_safe() {
    local args
    args=( )
    for word in "$@"; do
        word=\'${word//\'/"'\\''"}\'
        args+=( "$word" )
    done
    eval "${args[*]}"
}

引用是bash的语法变得真正混淆的地方。我没有引用word=${...},而我在数组中引用它。无论您是否引用内部替换语法。在单个赋值中,bash不会进行单词分割,而是在数组中进行分词。 (可以"${array[@]//source/target}" [[ $word =~ ^[a-zA-Z0-9_./]+$ ]] || word=${...} 并且一次性完成,但我们正在处理多个层次 引用已经。)

无论如何,这将评估单词并将它们传递回bash,引用if 他们中有奇怪的人物。

他们添加了一堆丑陋的引语,而这些引用可能并非如此 必要的,所以让我们补充一下:

{{1}}

这说,&#34;这个词匹配这个安全的正则表达式,或者我们引用它。&#34;这至少是合理的标准正则表达式语法,除了与其他所有语言不同,你通常不会划分正则表达式。