А если мы не хотим интерпретировать имена аргументов в командной строке как имена файлов? Тогда не надо обращаться к методам ввода без указания вызывающего объекта. Если вы хотите читать из стандартного ввода, укажите в качестве такого объекта STDIN, и все будет работать правильно.
Глобальная константа ARGVпредставляет список аргументов, переданных в командной строке. По сути дела, это массив.
n = ARGV.size
argstr = '"' + ARGV*"," + '"'
puts "Мне было передано аргументов: #{n}..."
puts "Вот они: #{argstr}"
puts "Заметьте, что ARGV[0] = #{ARGV[0]}"
Если запустить эту программу с аргументами red green blue, то она напечатает:
Мне было передано аргументов: 3...
Вот они: "red,green,blue"
Заметьте, что ARGV[0] = red
Ясно, что отдельно передавать число аргументов, как в былые времена, не нужно; эта информация — часть массива.
Привычных к старым соглашениям программистов может смутить также тот факт, что нулевой элемент массива — настоящий аргумент (а не, скажем, имя сценария). Нумерация аргументов начинается с нуля, а не с единицы, как в языке С и в различных интерпретаторах команд.
Не всегда Ruby удобен в качестве языка сценариев. Например, в языке bash для запуска внешней программы достаточно просто указать ее имя безо всякого дополнительного синтаксиса.
Оборотной стороной мощи и гибкости Ruby является более сложный синтаксис. Кроме того, функциональность разнесена по различным классам, модулям и библиотекам.
Это послужило основанием для создания библиотеки Shell, которая упрощает, к примеру, организацию конвейеров команд и перенаправление вывода в файл. Кроме того, она сводит воедино функциональность из разных источников, скрывая ее за интерфейсом объекта Shell. (На платформе Windows эта библиотека работает не во всех случаях.)
14.3.1. Использование библиотеки Shell для перенаправления ввода/вывода
В классе Shellдля создания объектов есть два метода: newи cd. Первый создает объект, ассоциированный с текущим каталогом, второй — объект, для которого рабочим будет указанный каталог.
require "shell"
sh1 = Shell.new # Работать в текущем каталоге.
sh2 = Shell.cd("/tmp/hal") # Работать в каталоге /tmp/hal.
Библиотека Shellопределяет несколько встроенных команд (например, echo, catи tee) в виде методов. Они всегда возвращают объекты класса Filter(как и определяемые пользователем команды, с которыми мы вскоре познакомимся).
Класс Filterпонимает, что такое перенаправление ввода/вывода. В нем определены методы (или операторы) <, >и |, которые ведут себя примерно так, как мы ожидаем по многолетнему опыту написания shell-сценариев.
Если методу перенаправления передать в качестве параметра строку, то она будет считаться именем файла. Если же параметром является объект IO, он используется для операций ввода/вывода. Примеры:
sh = Shell.new
# Вывести файл motd на stdout.
sh.cat("/etc/motd") > STDOUT
# Напечатать его еще раз.
(sh.cat < "/etc/motd") > STDOUT
(sh.echo "Это тест") > "myfile.txt"
# Добавить строку в конец файла /etc/motd.
sh.echo("Hello, world!") >> "/etc/motd"
# Вывести два файла на stdout и продублировать (tee) вывод в третий файл.
(sh.cat "file1" "file2") | (tee "file3") > STDOUT
Отметим, что у оператора >высокий приоритет. Скобки, которые вы видите в данном примере, в большинстве случаев обязательны. Вот два примера правильного использования и один — неправильного:
# Интерпретатор Ruby понимает такую конструкцию...
sh.cat("myfile.txt") > STDOUT
# ...и такую тоже.
(sh.cat "myfile.txt") > STDOUT
# TypeError! (ошибка связана с приоритетами).
sh.cat "myfile.txt" > STDOUT
Отметим еще, что можно «инсталлировать» системные команды по своему выбору. Для этого служит метод def_system_command. Ниже определяются два метода: lsи ll, которые выводят список файлов в текущем каталоге (в коротком и длинном формате).
# Имя метода совпадает с именем команды...
# Необходим только один параметр:
Shell.def_system_command "ls"
# А здесь должно быть два параметра:
Shell.def_system_command "ll", "ls -l"
sh = Shell.new
sh.ls > STDOUT # Короткий формат.
sh.ll > STDOUT # Длинный формат.
Вы, наверное, обратили внимание на то, что в большинстве случаев мы явно отправляем вывод объекту STDOUT. Связано это с тем, что объект Shellавтоматически вывод команд никуда не направляет. Он просто ассоциирует его с объектом Filter, который уже может быть связан с файлом или с объектом IO.
Читать дальше
Конец ознакомительного отрывка
Купить книгу