Почему при выполнении подстановки команды не отображается less?

Я сомневаюсь, что им это очень понравится, но, насколько я могу судить, их определение "свободного программного обеспечения" ничего подобного не упоминает. Кроме того, в свободном программном обеспечении вы можете исправлять такие недостатки, если они вам не нравятся.

Тем не менее, есть много других вещей, которые FSF считает -несвободными. Взгляните на список дистрибутивов Linux, которые FSF считает бесплатными . (Спойлер :Ubuntu здесь нет ). Честно говоря, я не слышал ни об одном из них, пока не заглянул в список.

У них также есть список наиболее распространенных дистрибутивов, о которых люди действительно слышали , включая причины, по которым они считают их -несвободными. (Спойлер :включает Ubuntu. И Arch, Debian, Fedora, Gentoo и Red Hat, среди прочих. Плюс все три больших BSD.)

Итак, мой ответ будет :возможно, но кого это волнует.

0
04.10.2019, 22:00
2 ответа
(trap : INT; echo "$(less <<< 'some text' >/dev/tty; echo done)")

lessпревратится в своего рода (un )причудливый cat, когда его стандартный вывод не является tty, как при использовании в подстановке команды (, где его стандартный вывод является каналом)[1].

При тестировании в интерактивном bash (, где управление заданиями включено по умолчанию ), подоболочка (...)гарантирует, что команда lessвыполняется как часть надлежащего приоритетного задания в терминал, без которого может быть невозможно приостановить его с помощью ^Z, завершить его с помощью ^Cи другими способами [2].

trap : INTзаставит подоболочку игнорировать ^C, не передавая это расположение своим потомкам.

Если команда является частью сценария оболочки, все процессы будут выполняться как часть одной и той же группы процессов/задания, но (...)все же может быть полезно для ограничения области ловушки INT.

[1] Вы даже не можете использовать его для вывода двоичных данных с красивым экранированием, если его стандартный вывод не является tty:

$ printf '\xee' | less -FXR
<EE>
$ printf '\xee' | less -FXR | cat
�$ 

[2] Есть много возможных сценариев того, что может произойти, и все они плохие. Например, в

$ ls -d $(less <<<'some text' >/dev/tty; pwd)

bashразветвит отдельный процесс, в котором будет выполняться двоичный файл ls, и запустит подстановку процесса $(...)в качестве его дочернего элемента , прежде чем переместит его в отдельную группу процессов/задание и выполнит двоичный файл.

Когда вы нажимаете ^Zвнутри less, он будет обработан lessкак обычно, но либо не сможет остановить его (, если оболочка и, следовательно, работа lessявляется лидером сеанса ), или вызовет остановку только less, но не его родительского процесса.

Когда вы нажмете ^Cвнутри less, он будет пойман и обработан less,но SIGINTтакже будет отправлено в основную оболочку (, которая является приоритетным заданием на терминале ), что заставит его вернуть следующее приглашение, а строка чтения bash и lessбудут конкурировать за ввод и изменяют свойства терминала, не подозревая друг о друге, что приводит к полной лаже.

Примечание

Все это относится к любой программе, запускаемой из подстановки команд, а не только к $(less...)примеру, например.

$ cat >foo <<'EOT'; chmod 755 foo
t=$(mktemp)
vi "$t" </dev/tty >/dev/tty 2>&1
echo "$t"
EOT
$ cat $(./foo)
# ^Z doesn't work in vi
3
28.01.2020, 02:14

В общем, echo $(somecmd)не очень полезен для любого somecmd. Вывод somecmdбудет расширен до аргументов echo, а затем echoвозьмет свои аргументы и напечатает их на своем выходе. Обычно вместо этого вы можете просто запустить somecmd.

Разница между этими двумя заключается в обычном :разделении и объединении слов -. echo $(somecmd)будет сжимать пробелы и расширять все, что выглядит как глобус имени файла(*.txt). Этого, конечно, не произойдет при запуске только somecmdили при запуске echo "$(somecmd)"с кавычками, хотя и удаляют все, кроме последней новой строки. также есть вероятность, что ваш echoрасширяет обратную косую черту -.

Что касается less, его цель — позволить интерактивный просмотр файлов или входных каналов, а для этого в значительной степени требуется терминал. Когда вы запускаете его в подстановке команд, вывод lessвместо этого подключается к каналу, и он возвращается к поведению, очень похожему на cat. (Кажется, я не могу найти упоминания о точном поведении на странице руководства.)


Теперь, если вам серьезно нужен сценарий, который запускается внутри подстановки команд, позволяя пользователю просматривать некоторые выходные данные и при этом возвращая некоторый другой текст посредством подстановки команд, вы можете творчески использовать перенаправления (, перефразируя mosvy's комментарий):

$ cat myscript
#!/bin/bash
echo this is the output

cat >&2 <<EOF
you can
browse this
with less
EOF
$ foo=$(./myscript 2> >(less > /dev/tty))

Стандартный вывод скрипта идет на подстановку команд, а вывод ошибки — на less, поэтому fooустанавливается на this is the output. Я не уверен, что это полезно, так как вы не сможете изменить значение, идущее к fooв интерактивном режиме, по крайней мере, только с помощью less.

Кроме того, такой запуск lessнарушает управление заданиями, поэтому нажатие Ctrl -C во время работы приводит к странному поведению и т. д.


Здесь, вероятно, было бы лучше просто использовать временный файл. Пусть myscriptзапишет результат в файл с именем в качестве аргумента (, то есть echo "$result" > "$1"),затем запустите:

tmp=$(mktemp)
myscript "$tmp"
cd "$(cat "$tmp")"
rm "$tmp"

Теперь myscriptможет запускать lessили другую интерактивную программу в обычном режиме, и проблем с контролем заданий быть не должно.

3
28.01.2020, 02:14

Теги

Похожие вопросы