Short:
Перенаправить потоки Perl и восстановить в конце, чтобы напечатать эту информацию, взятую сценарием оболочки
Или выведите, что last и сценарий оболочки может передать вывод на консоль и взять последнюю строку
Или использовать именованный канал (либо оболочка) или конкретные файловые дескрипторы (не csh
) для этой печати
Когда Perl-скрипт печатает это имя, вы можете присвоить его переменной в сценарии оболочки
#!/bin/csh
set DIR `perl -e'print "dir_name"'`
в то время как в bash
#!/bin/bash
DIR="$(perl -e'print "dir_name"')"
, где $(...)
предпочтительнее для подстановки команд.
Но тогда эти другие распечатки на консоль из сценария Perl должныбыть обработанным
- Одним из способов является перенаправление всех выходных данных в скрипте Perl, кроме той одной печати, что может управляться параметром командной строки (имя файла, куда перенаправлять, какой скрипт оболочки может распечатать)
Или, возьмите весь вывод Perl и передайте его на консоль,Астлайн - это необходимое «возвращение».Это накладывает бремя на скрипт Perl для печати этого последнего (возможно, в блоке END
).Вывод программы может быть распечатан из сценария оболочки после его завершения или построчно по мере ее выдачи.
Или используйте именованный канал (обе оболочки)или определенный файловый дескриптор (только bash
), в который Perl-скрипт может распечатать эту информацию.В этом случае его потоки идут прямо на консоль.
В вопросе явно упоминается csh
, поэтому он приводится ниже.Но я должен повторить старый и изношенный факт, что сценарии оболочки гораздо лучше выполняются в bash
, чем в csh
.Настоятельно рекомендую пересмотреть.
bash
Если вам нужен вывод программы на консоль по ходу, возьмите и напечатайте ее построчно
#!/bin/bash
while read line; do
echo "$line"
DIR=$line
done < <(perl script.pl)
echo "$DIR"
Или,если вам не нужен вывод на консоль до завершения сценария
#!/bin/bash
mapfile -t lines < <(perl script.pl)
DIR="${lines[-1]}"
printf '%s\n' "${lines[@]}" # print script.pl's output
Или используйте файловые дескрипторы для этого конкретного отпечатка
F=$(mktemp) # safe filename
exec 3> "$F" # open fd 3 to write to it
exec 4< "$F" # open fd 4 to read from it
rm -f "$F" # remove file(name) for safety; opened fd's can still access
perl -E'$fd=shift; say "...normal prints to STDOUT...";
open(FH, ">&=$fd") or die $!;
say FH "dirname";
close FH
' 3
read dir_name <&4
exec 3>&- # close them
exec 4<&-
echo "$dir_name"
Я не смог заставить его работатьс одним файловым дескриптором для чтения и записи (exec 3<> ...
), я думаю, потому что чтение не может перематывать после записи, поэтому используются отдельные дескрипторы.
С помощью сценария Perl (а не демонстрационной однострочной строки выше) передайте номер fd в качестве параметра командной строки.Сценарий может сделать это, только если он вызывается с этой опцией.
Или используйте именованный канал очень похоже на то, как это сделано для csh
ниже.Это, вероятно, лучше всего здесь, если вам не нравится манипулирование с программой STDOUT
.
csh
Перебирайте выходные данные программы (выполнено) строка за строкой
#!/bin/csh
foreach line ( "`perl script.pl`" )
echo "$line"
set dir_name = "$line"
end
echo "Directory name: $dir_name"
или сначала извлеките последнюю строку, а затем напечатайте весь вывод
#!/bin/csh
set lines = ( "`perl script.pl`" )
set dir_name = $lines[$#]
# Print program's output
while ( $#lines )
echo "$lines[1]"
shift lines
end
или используйте именованный канал
set fifo_name = "/tmp/fifo$$" # or use mktemp
mkfifo "$fifo_name"
( perl script.pl --fifo $fifo_name [other args] & )
set dir_name = `cat "$fifo_name"`
rm -f $fifo_name
echo "dir name from FIFO: $dir_name"
Команда Perlв фоновом режиме, поскольку блоки FIFO пока не написаны и read.Поэтому, если сценарий оболочки будет ждать завершения perl ...
, сценарий Perl будет блокироваться при записи в FIFO (поскольку он не читается), поэтому shell никогда не сможет его прочитать;мы бы зашли в тупик.Он также находится в подоболочке, с ( )
, чтобы избежать информационных отпечатков о фоновом задании.
Опция командной строки --fifo NAME
необходима, чтобы скрипт Perl знал, какой специальный файл использовать (и не делать этого, если эта опция отсутствует).
Для встроенного примера замените ( perl script ...)
на одну строчку:
( perl -E'$ff = shift; say qq(\t...normal prints to STDOUT...);
open FF, ">$ff" or die $!;
say FF "dir_name_$$";
close FF
' $fifo_name
& )
(разбитые строки для удобства чтения)