Как мне контролировать «имя» задания в Bash? - PullRequest
4 голосов
/ 23 декабря 2008

Я пытаюсь контролировать заголовки своих окон xterm, и мой ум наконец-то опередил мои знания. : -)

У меня есть три функции: одна устанавливает заголовок окна; тот, который принимает переданную команду, вызывает функцию title и выполняет команду; и тот, который возобновляет работу после использования 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 голосов
/ 19 июля 2014

человек Баш говорит:

fg [jobspec] Возобновите задание заданий на переднем плане и сделайте его текущим заданием. Если задание отсутствует, то оболочка понимает текущее задание используется.

А по «текущей работе»:

Символы %% и %+ относится к понятию оболочки текущего задания, которое является последним задание остановлено, когда оно было на переднем плане или началось в фоновом режиме.

Это то, что вы действительно хотите сделать; в любом случае эмулируйте, что делает команда 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"
}

Для вашей команды run во многих случаях команда eval будет делать то, что вы хочу:

eval "$@"

Но было бы неплохо защитить каждое слово одинарными кавычками, чтобы предотвратить переоценивая это:

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

В кавычках синтаксис bash становится действительно запутанным. Я не цитирую word=${...}, тогда как я цитирую это в массиве. Независимо от того, цитируетесь вы или нет, значение в синтаксисе подстановки. И в одном присваивании bash не разделяет слова, тогда как в массиве. (Можно сделать "${array[@]//source/target}" и сделать это одним выстрелом, но мы имеем дело с несколькими уровнями цитируя уже.)

В любом случае, это оценит слова и передаст их обратно в bash, если они указаны в них есть странные персонажи.

Это добавляет кучу уродливых цитат, где их, вероятно, нет необходимо, поэтому давайте добавим:

[[ $word =~ ^[a-zA-Z0-9_./]+$ ]] || word=${...}

Это говорит: «Слово соответствует этому безопасному регулярному выражению, или мы цитируем его». Это, по крайней мере, достаточно стандартный синтаксис регулярных выражений, за исключением того, что в отличие от любого другого языка, вы обычно не ограничиваете регулярное выражение.

0 голосов
/ 24 декабря 2008

Ну, это не идеально, но я нашел решение, которое по крайней мере правильно устанавливает мои заголовки:

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 для получения идентификатора процесса, затем он находит его с помощью ps, в котором указана правильная команда. К сожалению, ps кажется довольно медленным, вызывая заметную задержку (~ ¼ секунды) при возобновлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...