Анимация
JavaScript
|
Главная Библионтека Три стандартных файла для функции system (стандартный ввод, стандартный вывод и стандартный вывод ошибок) наследуются от Peii-процесса. Таким образом, результат выполнения команды date в приведенном выше примере направляется туда же, куда поступает результат выполнения функции print STDOUT - скорее всего, на дисплей вызвавшего ее пользователя. Поскольку вы запускаете shell, то можете переадресовать стандартный вывод, пользуясь обычными для /Ып/sh операциями переадресации. Например, чтобы направить результаты работы команды date в файл right now, нужно сделать что-то вроде этого: system("date >right now") 44 die "cannot create right now"; Ha этот раз мы не только посылаем результат команды date в файл, выполняя переадресацию в shell, но и проверяем статус возврата. Если статус возврата - значение "истина" (не нуль), это значит, что с командой shell что-то произошло, и функция die выполнит свою миссию. Данное правило обратно обычным правилам выполнения операций в Perl: ненулевое возвращаемое значение операции system, как правило, указывает на какую-то ошибку. Аргументом функции system может быть все, что пригодно для передачи в /Ып/sh, поэтому можно задавать сразу несколько команд, разделяя их точками с запятой или символами новой строки. Процессы, после которых указан символ &, запускаются, но программа не ждет их завершения, т.е. в данном случае все происходит аналогично тому, как если бы вы ввели в shell строку, которая заканчивается символом &. Вот пример задания команд date и who в shell с передачей результатов в файл, заданный Perl-переменной. Все это выполняется в фоновом режиме, чтобы для продолжения выполнения Perl-сценария не нужно было ждать завершения данного процесса. Swhere = "who out. " .++$i; # получить новое имя файла system "(date; who) >$where S"; В этом случае функция system возврашает код выхода shell и показывает таким образом, успешно ли был запущен фоновый процесс, по не сообщает, были ли успешно выполнены команды date и who. В этой заключенной в двойные кавычки строке производится интерполяция переменных, поэтому переменная $where заменяется своим значением (это делает Perl, а не shell). Если бы вы хотели обратиться к переменной shell с именем $ where, вам нужно было бы поставить перед знаком доллара обратную косую или использовать строку в одинарных кавычках. Помимо стандартных дескрипторов файлов, порожденный процесс наследует от родительского процесса много других вещей. Это текущее значение, заданное командой umask, текущий каталог и, конечно, идентификатор пользователя. Кроме того, порожденный процесс наследует все переменные среды. Эти переменные обычно изменяются командой csh setenv или же соответствующил( присваиванием и командой export shell (/bin/sh). Переменные среды используются многими утилитами, включая сам shell, для изменения порядка работы этих утилит и управления ими. В Perl предусмотрена возможность проверки и изменения текущих переменных среды посредством специального хеща, который называется %env. Каждый ключ этого хеща соответствует имени переменной среды, а соответствующее значение - значению переменной. Содержимое данного хеша отражает параметры среды, переданные Perl родительским shell; изменение хеша изменяет параметры среды, которую использует Perl и порожденные им процессы, но не среды, используемой родительскими процессами. Вот простая программа, которая работает, как printenv: foreach $кеу (sort keys %ENV) { print "$key = $ENV{$key}\n"; Обратите внимание: знак равенства здесь - это не символ операции присваивания, а просто текстовый символ, с помощью которого функция print выдает сообщения вида term=xterm или user=merlyn. Вот фрагмент программы, с помощью которого значение переменной PATH изменяется таким образом, чтобы поиск команды grep, запущенной функцией system, производился только в "обычных" местах: SoldPATH = SENV{"PATH"}; # сохранить предыдущий путь $ENVi"PATH"> = "/bin:/usr/bin:/usr/ucb" ; # ввести известный путь system("grep fred bedrock >output"); # запустить команду $ENV("PATH"} = $oldPATH; # восстановить предыдущий путь Как много текста придется набирать! Гораздо быстрее будет просто установить локальное значение для этого элемента хеша. Несмотря на наличие некоторых недостатков, операция local может делать одну вещь, которая не под силу операции ту: она способна присваивать временное значение одному элементу массива или хеша. local $ENV{"PATH"} = "/bin:/usr/bin:/usr/ucb"; system{"grep fred bedrock >output"); Функция system может принимать не один аргумент, а список аргументов. В этом случае Perl не передает список аргументов в shell, а рассматривает первый аргумент как подлежащую выполнению команду (при необходимости производится ее поиск согласно переменной path), а остальные аргументы - как аргументы команды без обычной для shell интерпретации. Другими словами, вам не нужно заключать в кавычки пробельные символы и беспокоиться об аргументах, которые содержат угловые скобки, потому что все это - просто символы, передаваемые в программу. Таким образом, следующие две команды эквивалентны: system "grep fred flintstone buffaloes"; # с использованием shell system "grep","fred flintstone","buffaloes"; # без использования shell Применение в функции system списка, а не одной строки, экономит также один процесс shell, поэтому поступайте так при любой возможности. (Если форма функции system с одним аргументом достаточно проста, Perl сам оптимизирует код, полностью убирая вызов shell и обращаясь к соответствующей программе непосредственно, как если бы вы использовали вызов функции с несколькими аргументами.) Вот еще один пример эквивалентных форм: gcfiles = ("fred.с","barney.с"); # что компилировать laoptions = ("-DHARD", "-DGRANITE") ; # опции system "ОС -о slate (aoptions (acfiles"; # с shell system "со", "-0", "slate", (aoptions, (defiles"; # без shell Использование обратных кавычек Еще один способ запуска процесса - заключить командную строку для /Ып/sh в обратные кавычки. Как и в shell, этот механизм запускает команду и ожидает ее заверщения, получая данные со стандартного вывода по мере их поступления: $now = "the time is now"."date; # получает текст и дату Значение переменной $now теперь представляет собой текст the time is now и результат выполнения команды date{\) (включая конечный символ новой строки): the time is now Fri Aug 13 23:59:59 PDT 1996 Если взятая в обратные кавычки команда используется не в скалярном, а в списочном контексте, то возвращается список строковых значений, каждое из которых представляет собой строку (оканчивающуюся символом новой строки*) из результата выполнения команды. В примере с командой date у нас был бы всего один элемент, потому что она выдала всего одну строку текста. Результат работы команды who выглядит так: merlyn tty32 Dec 7 19:41 fred ttylA Aug 31 07:02 barney ttylF Sep 1 09:22 Вот как можно получить этот результат в списочном контексте: foreach $ (who") f # один раз для каждой строки текста из who ($who, $where, $when) = / (\S+)\s+(\S+)\s+(. *) /,-print "$who on $where at $when\n"; Или символом, который у вас занесен в переменную $/ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 [ 58 ] 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |