Как Bash получает вывод выполненной программы?

Вам включали IPv6? Я не могу использовать pacman с IPv6, включенным на любой из моих машин. Необходимо попытаться отключить его.

5
10.12.2014, 21:20
2 ответа

Можно использовать perl (получить содержимое файла и заменить образцы на образцы + содержимое файла ):

perl -pe '$text=`cat insert.txt`; chomp($text); s/PAT/$&$text/' file.txt

добавить -i для редактирования на месте; g для добавления после каждого события PAT (образца), например:

perl -i -pe '$text=`cat insert.txt`; chomp($text); s/PAT/$&$text/g' file.txt

Другой способ, используя ed :

printf '%s\n' /PAT/s/PAT/\&\\ \/ - kb ". r insert.txt" j \'b j ,p q | ed -s file.txt

для редактирования по месту замените , p на w :

 printf '%s\n' /PAT/s/PAT/\&\\ \/ - kb ". r insert.txt" j \'b j w q | ed -s file.txt

Вероятно, никого не интересует, как это работает, но в любом случае printf передает список команд в ed :

/PAT/s/PAT/&\             #   set address to first line matching PAT and
/                         #   split the line right after PAT
-                         #   set address one line before (return to the line matching PAT)
kb                        #   mark the current line
. r insert.txt            #   insert content of insert.txt after this line         
j                         #   join current line and the next
'b                        #   set  address to marked line (return to the line matching PAT)
j                         #   join current line and the next one
,p                        #   print file content
q                         #   quit editor

Или без использования printf и | :

ed -s file.txt <<< $'/PAT/s/PAT/&\\\n/\n-\nkb\n. r insert.txt\nj\n\'b\nj\nw\nq\n'
-121--25573-

Это относится только к командам, указанным опциями -pre-invoke и -post-invoke , но не к командам, набору в конфигурации.

Это можно продемонстрировать, поместив эхо-команду в сценарий:

# cat > /tmp/pre-invoke.sh <<'EOF'
#!/bin/sh
echo This is testhook. Current action is $DPKG_HOOK_ACTION; exit 0
EOF
# chmod +x /tmp/pre-invoke.sh
# dpkg --pre-invoke=/tmp/pre-invoke.sh -i /var/cache/apt/archives/rsync_3.1.1-2+b1_amd64.deb
This is testhook. Current action is install
(Reading database ... 113857 files and directories currently installed.)
Preparing to unpack .../rsync_3.1.1-2+b1_amd64.deb ...
Unpacking rsync (3.1.1-2+b1) over (3.1.1-2+b1) ...
Setting up rsync (3.1.1-2+b1) ...
Restarting rsync daemon: rsync.
Processing triggers for man-db (2.6.7.1-1) ...
-121--175234-

Как дочерний процесс оболочки, ls наследует открытые файловые дескрипторы оболочки. И стандартные файловые дескрипторы (stdin, stdout, stderr (или 0, 1, 2)) соединены с псевдотерминалом, который обрабатывается эмулятором терминала.

Например (в системе Linux):

$ ls /proc/$$/fd -l
total 0
lrwx------ 1 muru muru 64 Dec 10 16:15 0 -> /dev/pts/3
lrwx------ 1 muru muru 64 Dec 10 16:15 1 -> /dev/pts/3
lrwx------ 1 muru muru 64 Dec 10 16:15 2 -> /dev/pts/3
lrwx------ 1 muru muru 64 Dec 10 16:15 255 -> /dev/pts/3
$ ls /proc/$(pgrep terminator -f)/fd -l | grep pts/3
lrwx------ 1 muru muru 64 Dec 10 16:15 26 -> /dev/pts/3

То есть выход ls , или, для этого, самой оболочки, обрабатывается не оболочкой, а эмулятором терминала (GNOME Terminal, terminator, xterm и т. д.).


Вы можете протестировать это:

В Linux найдите псевдотерминал ( pts ), используемый эмулятором терминала (скажем, GNOME Terminal):

$ ls -l /proc/$(pgrep -n gnome-terminal)/fd | grep pts
lrwx------ 1 muru muru 64 Dec 10 18:00 1 -> /dev/pts/1
lrwx------ 1 muru muru 64 Dec 10 18:00 15 -> /dev/pts/20
lrwx------ 1 muru muru 64 Dec 10 18:00 2 -> /dev/pts/1

Теперь нестандартные fds (кроме 0,1,2) gnome-terminal будут использоваться им для ввода и вывода оболочки. Эмулятор терминала считывает данные, отправляемые на этот PTS, и (после некоторой обработки, для цветов и т.д.) представляет их на экране. В этом случае это будет 15 , подключенный к pts/20 . Если я напишу что-то в эти pts, я могу ожидать, что оно появится в этом терминале:

enter image description here

Дальнейшее чтение:


Другой случай, где я делаю такие вещи, как:

echo $(ls)
a=$(date)
vim `command -v some_script`

называется Подстановка команд . При замене команды вывод команды захватывается самой оболочкой и никогда не доходит до терминала, если только вы не распечатаете его (например, echo $ (ls) ). Этот случай рассматривается в ответе Хауке Лагинга .

9
27.01.2020, 20:33

Оказывается, я неправильно понял вопрос в смысле подстановки команд. Только в этом случае оболочка участвует в обработке вывода.

Надеюсь, это тоже заинтересует ...

Я подключаюсь к оболочке с помощью strace -p 2140 перед запуском echo $ (/ bin / echo foo) в этом thell. Это часть результата:

pipe([3, 4])
pipe([5, 6])
...
read(3, "foo\n", 128)

Вот что происходит в дочернем процессе:

dup2(4, 1)
close(4)
close(3)
...
execve("/bin/echo", ...

Оболочка соединяет файловые дескрипторы 3 и 4, а затем выполняет разветвление. Дочерний процесс делает fd 4 своим stdout перед запуском новой программы. Таким образом, все, что дочерний элемент пишет в stdout , может быть прочитано родительской оболочкой на ее fd 3.

3
27.01.2020, 20:33

Теги

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