Как управлять заданием "имя" в 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 $*
</ctrl-z></ctrl-z>

Ну, я полагаю, это технически имя команды, выполняемой функцией run, но это не очень полезно знать в этом случае.

Итак, поскольку я не только достиг, но намного превысил пределы моих знаний о Bash, возможно, кто-то здесь может помочь мне исправить это.: -)

2 ответа

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

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


man bash говорит:

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

И в текущем задании:

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

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

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

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

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

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

licensed under cc by-sa 3.0 with attribution.