модуль Kernel
RubyGems добавляет метод gem, чтобы разрешить активацию определённых версий gem и переопределяет метод require в Kernel, чтобы сделать gems, как будто они находятся в $LOAD_PATH. Смотрите документацию этих методов для получения более подробной информации.
Модуль Kernel включён в класс Object, поэтому его методы доступны в каждом объекте Ruby.
Методы экземпляра Kernel документированы в классе Object, а методы модуля документированы здесь. Эти методы вызываются без получателя и поэтому могут вызываться в функциональном виде:
sprintf "%.1f", 1.234 #=> "1.2"
Что здесь
Модуль Kernel предоставляет методы, которые полезны для:
Преобразования
Запросы
-
- #__callee__
-
Возвращает вызываемое имя текущего метода в виде символа.
-
- #__dir__
-
Возвращает путь к каталогу, из которого вызван текущий метод.
-
- #__method__
-
Возвращает имя текущего метода в виде символа.
-
-
autoload? -
Возвращает файл, который должен быть загружен при ссылке на данный модуль.
-
-
-
block_given? -
Возвращает
true, если блоку был передан вызывающему методу.
-
-
-
caller -
Возвращает текущий стек выполнения в виде массива строк.
-
-
-
caller_locations -
Возвращает текущий стек выполнения в виде массива объектов
Thread::Backtrace::Location.
-
-
-
class -
Возвращает класс
self.
-
-
-
frozen? -
Возвращает, заморожен ли
self.
-
-
-
global_variables -
Возвращает массив глобальных переменных в виде символов.
-
-
-
local_variables -
Возвращает массив локальных переменных в виде символов.
-
-
-
test -
Выполняет указанные тесты для данного файла или пары файлов.
-
Выход
-
-
abort -
Завершает текущий процесс после вывода заданных аргументов.
-
-
-
at_exit -
Выполняет данный блок при завершении процесса.
-
-
-
exit -
Завершает текущий процесс после вызова всех зарегистрированных
at_exitобработчиков.
-
-
-
exit! -
Завершает текущий процесс без вызова зарегистрированных
at_exitобработчиков.
-
Исключения
-
-
catch -
Выполняет данный блок, возможно перехватывая брошенный объект.
-
-
-
throw -
Возвращается из активного блока catch, ожидающего заданный тег.
-
IO
-
-
gets -
Возвращает и присваивает
$_следующую строку из текущего ввода.
-
-
-
p -
Выводит результат inspect объекта в стандартный вывод.
-
-
-
pp -
Выводит объекты в красивом формате.
-
-
-
print -
Выводит заданные объекты в стандартный вывод без новой строки.
-
-
-
printf -
Выводит строку, полученную путём применения заданной строки формата к дополнительным аргументам.
-
-
-
putc -
Эквивалентно <tt.$stdout.putc(object)</tt> для данного объекта.
-
-
-
puts -
Эквивалентно
$stdout.puts(*objects)для заданных объектов.
-
-
-
readlines -
Возвращает массив оставшихся строк из текущего ввода.
-
Программы
-
-
lambda -
Возвращает лямбда-программу для данного блока.
-
Отслеживание
-
-
set_trace_func -
Устанавливает данную программку как обработчик для отслеживания или отключает отслеживание, если указано
nil.
-
-
-
trace_var -
Начинает отслеживать присваивания заданной глобальной переменной.
-
-
-
untrace_var -
Отключает отслеживание присваиваний заданной глобальной переменной.
-
Подпроцессы
-
- #‘cmd`
-
Возвращает стандартный вывод выполнения
cmdв дочернем процессе.
-
-
exec -
Заменяет текущий процесс новым процессом.
-
-
-
fork -
Создает два процесса, копируя текущий.
-
-
-
spawn -
Выполняет заданную команду и возвращает её pid без ожидания завершения.
-
-
-
system -
Выполняет заданную команду в дочернем процессе.
-
Загрузка
-
-
autoload -
Регистрирует файл для загрузки при первом использовании заданной константы.
-
-
-
load -
Загружает указанный файл Ruby.
-
-
-
require -
Загружает указанный файл Ruby, если он ещё не загружен.
-
-
-
require_relative -
Загружает файл Ruby, путь к которому относительный к вызывающему файлу, если он ещё не загружен.
-
Выдача
-
-
tap -
Вызывает заданный блок с
self; возвращаетself.
-
-
-
then(алиасyield_self) -
Вызывает блок с
selfи возвращает результат блока.
-
Случайные значения
-
-
rand -
Возвращает псевдослучайное число с плавающей точкой, строго между 0.0 и 1.0.
-
-
-
srand -
Инициализирует генератор псевдослучайных чисел заданным числом.
-
Другие
-
-
eval -
Вычисляет заданную строку как код Ruby.
-
-
-
loop -
Повторяет выполнение заданного блока.
-
-
-
sleep -
Приостанавливает текущую нить на заданное количество секунд.
-
-
-
syscall -
Выполняет системный вызов операционной системы.
-
-
-
trap -
Устанавливает обработку системных сигналов.
-
-
-
warn -
Выводит предупреждение на основе заданных сообщений и опций.
-
Публичные методы класса
# File lib/uri/common.rb, line 688
def URI(uri)
if uri.is_a?(URI::Generic)
uri
elsif uri = String.try_convert(uri)
URI.parse(uri)
else
raise ArgumentError,
"bad argument (expected URI object or URI string)"
end
end Возвращает uri преобразованный в объект URI.
# File lib/pp.rb, line 624
def pp(*objs)
objs.each {|obj|
PP.pp(obj)
}
objs.size <= 1 ? objs.first : objs
end Выводит аргументы в красивом виде.
pp возвращает аргументы.
Публичные методы экземпляра
static VALUE
rb_f_array(VALUE obj, VALUE arg)
{
return rb_Array(arg);
} Возвращает arg как Array.
Сначала пытается вызвать to_ary для arg, затем to_a. Если arg не отвечает на to_ary или to_a, возвращает Array длиной 1, содержащий arg.
Если to_ary или to_a возвращают что-то отличное от Array, генерирует исключение TypeError.
Array(["a", "b"]) #=> ["a", "b"] Array(1..5) #=> [1, 2, 3, 4, 5] Array(key: :value) #=> [[:key, :value]] Array(nil) #=> [] Array(1) #=> [1]
static VALUE
f_BigDecimal(int argc, VALUE *argv, VALUE self)
{
VALUE val, digs_v, opts = Qnil;
argc = rb_scan_args(argc, argv, "11:", &val, &digs_v, &opts);
int exception = opts_exception_p(opts);
size_t digs = SIZE_MAX; /* this means digs is omitted */
if (argc > 1) {
digs_v = rb_to_int(digs_v);
if (FIXNUM_P(digs_v)) {
long n = FIX2LONG(digs_v);
if (n < 0)
goto negative_digs;
digs = (size_t)n;
}
else {
if (RBIGNUM_NEGATIVE_P(digs_v)) {
negative_digs:
if (!exception)
return Qnil;
rb_raise(rb_eArgError, "negative precision");
}
digs = NUM2SIZET(digs_v);
}
}
return rb_convert_to_BigDecimal(val, digs, exception);
} Returns the \BigDecimal converted from +value+ with a precision of +ndigits+ decimal digits. When +ndigits+ is less than the number of significant digits in the value, the result is rounded to that number of digits, according to the current rounding mode; see BigDecimal.mode.
Возвращает value преобразованный в BigDecimal, в зависимости от типа value:
-
Integer,Float,Rational,Complexили BigDecimal: преобразуется напрямую:# Integer, Complex, or BigDecimal value does not require ndigits; ignored if given. BigDecimal(2) # => 0.2e1 BigDecimal(Complex(2, 0)) # => 0.2e1 BigDecimal(BigDecimal(2)) # => 0.2e1 # Float or Rational value requires ndigits. BigDecimal(2.0, 0) # => 0.2e1 BigDecimal(Rational(2, 1), 0) # => 0.2e1
-
Строка: преобразуется путем анализа, если она содержит целое или число с плавающей запятой; начальные и конечные пробелы игнорируются:
# String does not require ndigits; ignored if given. BigDecimal('2') # => 0.2e1 BigDecimal('2.0') # => 0.2e1 BigDecimal('0.2e1') # => 0.2e1 BigDecimal(' 2.0 ') # => 0.2e1 -
Другой тип, который отвечает на метод
:to_str: сначала преобразуется в строку, затем в BigDecimal, как описано выше. -
Другой тип:
-
Генерирует исключение, если аргумент ключевого слова
exceptionравенtrue. -
Возвращает
nil, если аргумент ключевого словаexceptionравенtrue.
-
Генерирует исключение, если value вычисляется как Float, а digits больше, чем Float::DIG + 1.
static VALUE
nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
{
VALUE a1, a2, opts = Qnil;
int raise = TRUE;
if (rb_scan_args(argc, argv, "11:", &a1, &a2, &opts) == 1) {
a2 = Qundef;
}
if (!NIL_P(opts)) {
raise = rb_opts_exception_p(opts, raise);
}
if (argc > 0 && CLASS_OF(a1) == rb_cComplex && a2 == Qundef) {
return a1;
}
return nucomp_convert(rb_cComplex, a1, a2, raise);
} Возвращает x+i*y;
Complex(1, 2) #=> (1+2i)
Complex('1+2i') #=> (1+2i)
Complex(nil) #=> TypeError
Complex(1, nil) #=> TypeError
Complex(1, nil, exception: false) #=> nil
Complex('1+2', exception: false) #=> nil
Синтаксис строковой формы:
string form = extra spaces , complex , extra spaces ;
complex = real part | [ sign ] , imaginary part
| real part , sign , imaginary part
| rational , "@" , rational ;
real part = rational ;
imaginary part = imaginary unit | unsigned rational , imaginary unit ;
rational = [ sign ] , unsigned rational ;
unsigned rational = numerator | numerator , "/" , denominator ;
numerator = integer part | fractional part | integer part , fractional part ;
denominator = digits ;
integer part = digits ;
fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
imaginary unit = "i" | "I" | "j" | "J" ;
sign = "-" | "+" ;
digits = digit , { digit | "_" , digit };
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
extra spaces = ? \s* ? ; См. String#to_c.
# File kernel.rb, line 171
def Float(arg, exception: true)
if Primitive.mandatory_only?
Primitive.rb_f_float1(arg)
else
Primitive.rb_f_float(arg, exception)
end
end Возвращает arg, преобразованный в число с плавающей запятой. Типы Numeric преобразуются напрямую, а с исключением для String и nil остальные преобразуются с использованием arg.to_f. Преобразование String с недопустимыми символами приведет к ArgumentError. Преобразование nil создает TypeError. Исключения можно подавить, передав exception: false.
Float(1) #=> 1.0
Float("123.456") #=> 123.456
Float("123.0_badstring") #=> ArgumentError: invalid value for Float(): "123.0_badstring"
Float(nil) #=> TypeError: can't convert nil into Float
Float("123.0_badstring", exception: false) #=> nil
static VALUE
rb_f_integer(int argc, VALUE *argv, VALUE obj)
{
VALUE arg = Qnil, opts = Qnil;
int base = 0;
if (argc > 1) {
int narg = 1;
VALUE vbase = rb_check_to_int(argv[1]);
if (!NIL_P(vbase)) {
base = NUM2INT(vbase);
narg = 2;
}
if (argc > narg) {
VALUE hash = rb_check_hash_type(argv[argc-1]);
if (!NIL_P(hash)) {
opts = rb_extract_keywords(&hash);
if (!hash) --argc;
}
}
}
rb_check_arity(argc, 1, 2);
arg = argv[0];
return rb_convert_to_integer(arg, base, opts_exception_p(opts));
} Преобразует arg в Integer. Типы Numeric преобразуются напрямую (с числами с плавающей запятой, которые усекаются). base (0 или от 2 до 36) - это основание для целочисленного строкового представления. Если arg является String, когда base опущен или равен нулю, учитываются индикаторы основания (0, 0b и 0x). В любом случае строки должны состоять только из одной или нескольких цифр, за исключением того, что знак, одно подчеркивание между двумя цифрами и начальные/конечные пробелы являются необязательными. Это поведение отличается от поведения String#to_i. Нестроковые значения будут преобразованы, сначала попытавшись to_int, затем to_i.
Передача nil вызывает TypeError, а передача String, которая не соответствует числовому представлению, вызывает ArgumentError. Это поведение можно изменить, передав exception: false, в этом случае неконвертируемое значение вернет nil.
Integer(123.999) #=> 123
Integer("0x1a") #=> 26
Integer(Time.new) #=> 1204973019
Integer("0930", 10) #=> 930
Integer("111", 2) #=> 7
Integer(" +1_0 ") #=> 10
Integer(nil) #=> TypeError: can't convert nil into Integer
Integer("x") #=> ArgumentError: invalid value for Integer(): "x"
Integer("x", exception: false) #=> nil
static VALUE
path_f_pathname(VALUE self, VALUE str)
{
if (CLASS_OF(str) == rb_cPathname)
return str;
return rb_class_new_instance(1, &str, rb_cPathname);
} Создает новый объект Pathname из данной строки, path, и возвращает объект pathname.
Чтобы использовать этот конструктор, необходимо сначала подключить расширение стандартной библиотеки Pathname.
require 'pathname'
Pathname("/home/zzak")
#=> #<Pathname:/home/zzak>
См. также Pathname::new для получения дополнительной информации.
static VALUE
nurat_f_rational(int argc, VALUE *argv, VALUE klass)
{
VALUE a1, a2, opts = Qnil;
int raise = TRUE;
if (rb_scan_args(argc, argv, "11:", &a1, &a2, &opts) == 1) {
a2 = Qundef;
}
if (!NIL_P(opts)) {
raise = rb_opts_exception_p(opts, raise);
}
return nurat_convert(rb_cRational, a1, a2, raise);
} Возвращает x/y или arg как Rational.
Rational(2, 3) #=> (2/3)
Rational(5) #=> (5/1)
Rational(0.5) #=> (1/2)
Rational(0.3) #=> (5404319552844595/18014398509481984)
Rational("2/3") #=> (2/3)
Rational("0.3") #=> (3/10)
Rational("10 cents") #=> ArgumentError
Rational(nil) #=> TypeError
Rational(1, nil) #=> TypeError
Rational("10 cents", exception: false) #=> nil
Синтаксис строковой формы:
string form = extra spaces , rational , extra spaces ;
rational = [ sign ] , unsigned rational ;
unsigned rational = numerator | numerator , "/" , denominator ;
numerator = integer part | fractional part | integer part , fractional part ;
denominator = digits ;
integer part = digits ;
fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
sign = "-" | "+" ;
digits = digit , { digit | "_" , digit } ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
extra spaces = ? \s* ? ; См. также String#to_r.
static VALUE
rb_f_string(VALUE obj, VALUE arg)
{
return rb_String(arg);
} Возвращает arg как String.
Сначала пытается вызвать его метод to_str, затем его метод to_s.
String(self) #=> "main" String(self.class) #=> "Object" String(123456) #=> "123456"
static VALUE
rb_f_callee_name(VALUE _)
{
ID fname = prev_frame_callee(); /* need *callee* ID */
if (fname) {
return ID2SYM(fname);
}
else {
return Qnil;
}
} Возвращает вызываемое имя текущего метода как Symbol. Если вызывается за пределами метода, возвращает nil.
static VALUE
f_current_dirname(VALUE _)
{
VALUE base = rb_current_realfilepath();
if (NIL_P(base)) {
return Qnil;
}
base = rb_file_dirname(base);
return base;
} Возвращает канонизированный абсолютный путь к каталогу файла, из которого вызывается этот метод. Это означает, что символические ссылки в пути разрешаются. Если __FILE__ равно nil, возвращает nil. Возвращаемое значение равно File.dirname(File.realpath(__FILE__)).
static VALUE
rb_f_method_name(VALUE _)
{
ID fname = prev_frame_func(); /* need *method* ID */
if (fname) {
return ID2SYM(fname);
}
else {
return Qnil;
}
} Возвращает имя в определении текущего метода как Symbol. Если вызывается за пределами метода, возвращает nil.
static VALUE
rb_f_backquote(VALUE obj, VALUE str)
{
VALUE port;
VALUE result;
rb_io_t *fptr;
SafeStringValue(str);
rb_last_status_clear();
port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
if (NIL_P(port)) return rb_str_new(0,0);
GetOpenFile(port, fptr);
result = read_all(fptr, remain_size(fptr), Qnil);
rb_io_close(port);
RFILE(port)->fptr = NULL;
rb_io_fptr_finalize(fptr);
RB_GC_GUARD(port);
return result;
} Возвращает стандартный вывод выполнения cmd в подпроцессе. Встроенный синтаксис %x{...} использует этот метод. Устанавливает $? в статус процесса.
`date` #=> "Wed Apr 9 08:56:30 CDT 2003\n" `ls testdir`.split[1] #=> "main.rb" `echo oops && exit 99` #=> "oops\n" $?.exitstatus #=> 99
static VALUE
f_abort(int c, const VALUE *a, VALUE _)
{
rb_f_abort(c, a);
UNREACHABLE_RETURN(Qnil);
} Немедленно завершает выполнение, фактически вызывая Kernel.exit(false). Если указано msg, оно выводится в STDERR перед завершением.
static VALUE
rb_f_at_exit(VALUE _)
{
VALUE proc;
if (!rb_block_given_p()) {
rb_raise(rb_eArgError, "called without a block");
}
proc = rb_block_proc();
rb_set_end_proc(rb_call_end_proc, proc);
return proc;
} Преобразует блок в объект Proc (и тем самым связывает его в момент вызова) и регистрирует его для выполнения при выходе из программы. Если зарегистрировано несколько обработчиков, они выполняются в обратном порядке регистрации.
def do_at_exit(str1)
at_exit { print str1 }
end
at_exit { puts "cruel world" }
do_at_exit("goodbye ")
exit
выводит:
goodbye cruel world
static VALUE
rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
{
VALUE klass = rb_class_real(rb_vm_cbase());
if (!klass) {
rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
}
return rb_mod_autoload(klass, sym, file);
} Регистрирует имя_файла для загрузки (с помощью Kernel::require) в первый раз, когда к модулю (который может быть String или символом) обращаются.
autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
static VALUE
rb_f_autoload_p(int argc, VALUE *argv, VALUE obj)
{
/* use rb_vm_cbase() as same as rb_f_autoload. */
VALUE klass = rb_vm_cbase();
if (NIL_P(klass)) {
return Qnil;
}
return rb_mod_autoload_p(argc, argv, klass);
} Возвращает имя_файла для загрузки, если имя зарегистрировано как autoload.
autoload(:B, "b") autoload?(:B) #=> "b"
static VALUE
rb_f_binding(VALUE self)
{
return rb_binding_new();
} Возвращает объект Binding, описывающий привязку переменных и методов в точке вызова. Этот объект может быть использован при вызове eval для выполнения оцениваемой команды в этой среде. Смотрите также описание класса Binding.
def get_binding(param)
binding
end
b = get_binding("hello")
eval("param", b) #=> "hello"
static VALUE
rb_f_block_given_p(VALUE _)
{
rb_execution_context_t *ec = GET_EC();
rb_control_frame_t *cfp = ec->cfp;
cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
return RBOOL(cfp != NULL && VM_CF_BLOCK_HANDLER(cfp) != VM_BLOCK_HANDLER_NONE);
} Возвращает true , если yield будет выполнять блок в текущем контексте. Форма iterator? слабо устаревшая.
def try
if block_given?
yield
else
"no block"
end
end
try #=> "no block"
try { "hello" } #=> "hello"
try do "hello" end #=> "hello"
static VALUE
rb_callcc(VALUE self)
{
volatile int called;
volatile VALUE val = cont_capture(&called);
if (called) {
return val;
}
else {
return rb_yield(val);
}
} Генерирует объект Continuation, который передается ассоциированному блоку. Вам необходимо require 'continuation' перед использованием этого метода. Выполнение cont.call приведет к возврату callcc (как и проход до конца блока). Значение, возвращаемое callcc, является значением блока или значением, переданным в cont.call. См. класс Continuation для получения дополнительных сведений. Также см. Kernel#throw для альтернативного механизма разматывания стека вызовов.
static VALUE
rb_f_caller(int argc, VALUE *argv, VALUE _)
{
return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 1);
} Возвращает текущий стек выполнения — массив, содержащий строки в формате file:line или file:line: in `method'.
Необязательный параметр start определяет количество начальных записей стека, которые следует пропустить сверху.
Необязательный параметр length может быть использован для ограничения количества возвращаемых записей стека.
Возвращает nil если start больше размера текущего стека выполнения.
Необязательно можно передать диапазон, который вернёт массив, содержащий записи в указанном диапазоне.
def a(skip) caller(skip) end def b(skip) a(skip) end def c(skip) b(skip) end c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10:in `<main>'"] c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11:in `<main>'"] c(2) #=> ["prog:8:in `c'", "prog:12:in `<main>'"] c(3) #=> ["prog:13:in `<main>'"] c(4) #=> [] c(5) #=> nil
static VALUE
rb_f_caller_locations(int argc, VALUE *argv, VALUE _)
{
return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 0);
} Возвращает текущий стек выполнения — массив, содержащий объекты местоположений трассировки.
См. Thread::Backtrace::Location для получения дополнительной информации.
Необязательный параметр start определяет количество начальных записей стека, которые следует пропустить сверху.
Необязательный параметр length может быть использован для ограничения количества возвращаемых записей стека.
Возвращает nil если start больше размера текущего стека выполнения.
Необязательно можно передать диапазон, который вернёт массив, содержащий записи в указанном диапазоне.
static VALUE
rb_f_catch(int argc, VALUE *argv, VALUE self)
{
VALUE tag = rb_check_arity(argc, 0, 1) ? argv[0] : rb_obj_alloc(rb_cObject);
return rb_catch_obj(tag, catch_i, 0);
} catch выполняет свой блок. Если throw не вызывается, блок выполняется нормально, и catch возвращает значение последнего вычисленного выражения.
catch(1) { 123 } # => 123
Если throw(tag2, val) вызывается, Ruby ищет в стеке блок catch с tag таким же object_id как тег2. При обнаружении блок прекращает выполнение и возвращает val (или nil если второму аргументу throw не было передано).
catch(1) { throw(1, 456) } # => 456
catch(1) { throw(1) } # => nil
При передаче tag в качестве первого аргумента, catch передает его как параметр блока.
catch(1) {|x| x + 2 } # => 3
Если tag не указан, catch передаёт новый уникальный объект (как в Object.new) как параметр блока. Этот объект затем может быть использован в качестве аргумента к throw, и будет соответствовать правильному catch блоку.
catch do |obj_A|
catch do |obj_B|
throw(obj_B, 123)
puts "This puts is not reached"
end
puts "This puts is displayed"
456
end
# => 456
catch do |obj_A|
catch do |obj_B|
throw(obj_A, 123)
puts "This puts is still not reached"
end
puts "Now this puts is also not reached"
456
end
# => 123
static VALUE
rb_f_chomp(int argc, VALUE *argv, VALUE _)
{
VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chomp"), argc, argv);
rb_lastline_set(str);
return str;
} Эквивалентно $_ = $_.chomp(string). См. String#chomp. Доступно только при указании опций командной строки -p/-n.
static VALUE
rb_f_chop(VALUE _)
{
VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chop"), 0, 0);
rb_lastline_set(str);
return str;
} Эквивалентно ($_.dup).chop!, за исключением того, что nil никогда не возвращается. См. String#chop!. Доступно только при указании опций командной строки -p/-n.
# File kernel.rb, line 18 def class Primitive.attr! 'inline' Primitive.cexpr! 'rb_obj_class(self)' end
Возвращает класс объекта. Этот метод всегда должен вызываться со явным получателем, так как class также является зарезервированным словом в Ruby.
1.class #=> Integer self.class #=> Object
# File kernel.rb, line 47 def clone(freeze: nil) Primitive.rb_obj_clone2(freeze) end
Создаёт поверхностную копию объекта — копируются переменные экземпляра объекта, но не объекты, на которые они ссылаются. clone копирует состояние замороженного значения объекта, если необязательный ключевой аргумент :freeze не задан со значением false или true. Также см. обсуждение в Object#dup.
class Klass attr_accessor :str end s1 = Klass.new #=> #<Klass:0x401b3a38> s1.str = "Hello" #=> "Hello" s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello"> s2.str[1,4] = "i" #=> "i" s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">" s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
Этот метод может иметь поведение, специфичное для класса. В этом случае это поведение будет документировано в методе #initialize_copy класса.
VALUE
rb_f_eval(int argc, const VALUE *argv, VALUE self)
{
VALUE src, scope, vfile, vline;
VALUE file = Qundef;
int line = 1;
rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
SafeStringValue(src);
if (argc >= 3) {
StringValue(vfile);
}
if (argc >= 4) {
line = NUM2INT(vline);
}
if (!NIL_P(vfile))
file = vfile;
if (NIL_P(scope))
return eval_string_with_cref(self, src, NULL, file, line);
else
return eval_string_with_scope(scope, src, file, line);
} Вычисляет выражение(я) Ruby в строке. Если указана привязка, которая должна быть объектом Binding, вычисление выполняется в его контексте. Если необязательные параметры имя_файла и номер_строки присутствуют, они будут использоваться при сообщении об ошибках синтаксиса.
def get_binding(str)
return binding
end
str = "hello"
eval "str + ' Fred'" #=> "hello Fred"
eval "str + ' Fred'", get_binding("bye") #=> "bye Fred"
static VALUE
f_exec(int c, const VALUE *a, VALUE _)
{
rb_f_exec(c, a);
UNREACHABLE_RETURN(Qnil);
} Заменяет текущий процесс, выполняя заданную внешнюю команду, которая может иметь один из следующих форматов:
-
exec(commandline) -
строка командной строки, которая передаётся стандартной оболочке
-
exec(cmdname, arg1, ...) -
имя команды и один или более аргументов (без оболочки)
-
exec([cmdname, argv0], arg1, ...) -
имя команды, argv и ноль или более аргументов (без оболочки)
В первом формате строка воспринимается как командная строка, которая подвергается расширению оболочки перед выполнением.
Стандартная оболочка всегда означает "/bin/sh" в системах Unix-подобного типа, в противном случае ENV["RUBYSHELL"] или ENV["COMSPEC"] в Windows и подобных системах. Команда передаётся в качестве аргумента переключателю "-c" оболочки, за исключением случаев COMSPEC.
Если строка из первого формата (exec("command")) следует этим простым правилам:
-
нет метасимволов
-
не начинается с зарезервированного слова оболочки или специальной встроенной команды
-
Ruby вызывает команду напрямую без оболочки
Вы можете принудительно вызвать оболочку, добавив «;» в строку (поскольку «;» является метасимволом).
Обратите внимание, что это поведение можно наблюдать по полученному pid (возвращаемое значение spawn() и IO#pid для IO.popen) — это pid вызываемой команды, а не оболочки.
Во втором формате (exec("command1", "arg1", ...)) первый элемент используется как имя команды, а остальные передаются в качестве параметров команде без расширения оболочки.
В третьем формате (exec(["command", "argv0"], "arg1", ...)) в начале команды задаётся двухелементный массив, где первый элемент — это выполняемая команда, а второй — используется как значение argv[0] , которое может отображаться в списках процессов.
Для выполнения команды используются системные вызовы exec(2), поэтому выполняемая команда может унаследовать часть окружения исходной программы (включая открытые дескрипторы файлов).
Это поведение изменяется с помощью заданных параметров env и options. Подробности см. в ::spawn.
Если команда не может быть выполнена (обычно ошибка Errno::ENOENT, когда она не найдена), возникает исключение SystemCallError.
Этот метод изменяет атрибуты процесса в соответствии с заданными options перед системным вызовом exec(2). Дополнительные сведения о заданных options см. в ::spawn.
Изменённые атрибуты могут сохраниться, если системный вызов exec(2) завершится ошибкой.
Например, жёсткие ограничения ресурсов не восстанавливаются.
Рассмотрите возможность создания дочернего процесса с помощью ::spawn или Kernel#system, если это неприемлемо.
exec "echo *" # echoes list of files in current directory # never get here exec "echo", "*" # echoes an asterisk # never get here
static VALUE
f_exit(int c, const VALUE *a, VALUE _)
{
rb_f_exit(c, a);
UNREACHABLE_RETURN(Qnil);
} Инициирует завершение скрипта Ruby, вызвав исключение SystemExit. Это исключение может быть перехвачено. Необязательный параметр используется для возврата кода состояния в вызывающую среду. true и FALSE значения status соответствуют успеху и неудаче соответственно. Интерпретация других целых значений зависит от системы.
begin exit puts "never get here" rescue SystemExit puts "rescued a SystemExit exception" end puts "after begin block"
возвращает:
rescued a SystemExit exception after begin block
Непосредственно перед завершением Ruby выполняет любые функции at_exit (см. Kernel::at_exit) и выполняет все финализаторы объектов (см. ObjectSpace::define_finalizer).
at_exit { puts "at_exit function" }
ObjectSpace.define_finalizer("string", proc { puts "in finalizer" })
exit
возвращает:
at_exit function in finalizer
static VALUE
rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
{
int istatus;
if (rb_check_arity(argc, 0, 1) == 1) {
istatus = exit_status_code(argv[0]);
}
else {
istatus = EXIT_FAILURE;
}
_exit(istatus);
UNREACHABLE_RETURN(Qnil);
} Немедленно завершает процесс. Обработчики выхода не выполняются. status возвращается в базовую систему в качестве кода выхода.
Process.exit!(true)
Без аргументов, вызывает исключение в $! или вызывает RuntimeError, если $! равно nil. С одним аргументом, вызывает RuntimeError с указанной строкой в качестве сообщения. В противном случае, первый параметр должен быть классом Exception (или другим объектом, который возвращает объект Exception при отправке сообщения exception). Необязательный второй параметр устанавливает сообщение, связанное с исключением (доступно через Exception#message), а третий параметр — массив информации обратного вызова (доступен через Exception#backtrace). Причина сгенерированного исключения (доступно через Exception#cause) автоматически устанавливается в «текущее» исключение ($!), если таковое имеется. Альтернативное значение, либо объект Exception, или nil, может быть указано через аргумент :cause.
Исключения перехватываются блоком rescue в блоках begin...end.
raise "Failed to create socket" raise ArgumentError, "No parameters", caller
static VALUE
rb_f_fork(VALUE obj)
{
rb_pid_t pid;
pid = rb_call_proc__fork();
if (pid == 0) {
if (rb_block_given_p()) {
int status;
rb_protect(rb_yield, Qundef, &status);
ruby_stop(status);
}
return Qnil;
}
return PIDT2NUM(pid);
} Создаёт дочерний процесс. Если указан блок, этот блок выполняется в дочернем процессе, и дочерний процесс завершается с кодом 0. В противном случае, системный вызов fork возвращается дважды, один раз в родительском процессе, возвращая идентификатор процесса дочернего процесса, и один раз в дочернем процессе, возвращая nil. Дочерний процесс может завершиться с помощью Kernel.exit!, чтобы избежать выполнения функций at_exit. Родительский процесс должен использовать Process.wait для сбора статусов завершения своих дочерних процессов или использовать Process.detach для регистрации отсутствия интереса к их статусу; в противном случае операционная система может накапливать зомби-процессы.
Поток, вызывающий fork, является единственным потоком в созданном дочернем процессе. fork не копирует другие потоки.
Если fork недоступен, Process.respond_to?(:fork) возвращает false.
Обратите внимание, что fork(2) недоступен на некоторых платформах, таких как Windows и NetBSD 4. Поэтому вместо fork() следует использовать spawn().
Возвращает строку, полученную путём применения format_string к дополнительным аргументам. В строке формата все символы, кроме последовательностей формата, копируются в результат.
Синтаксис последовательности формата следующий:
%[flags][width][.precision]type
Последовательность формата состоит из символа процента, за которым следуют необязательные флаги, ширина и индикаторы точности, а затем завершается типом поля. Тип поля управляет тем, как соответствующий аргумент sprintf должен интерпретироваться, а флаги изменяют эту интерпретацию.
Символы типа поля:
Field | Integer Format
------+--------------------------------------------------------------
b | Convert argument as a binary number.
| Negative numbers will be displayed as a two's complement
| prefixed with `..1'.
B | Equivalent to `b', but uses an uppercase 0B for prefix
| in the alternative format by #.
d | Convert argument as a decimal number.
i | Identical to `d'.
o | Convert argument as an octal number.
| Negative numbers will be displayed as a two's complement
| prefixed with `..7'.
u | Identical to `d'.
x | Convert argument as a hexadecimal number.
| Negative numbers will be displayed as a two's complement
| prefixed with `..f' (representing an infinite string of
| leading 'ff's).
X | Equivalent to `x', but uses uppercase letters.
Field | Float Format
------+--------------------------------------------------------------
e | Convert floating point argument into exponential notation
| with one digit before the decimal point as [-]d.dddddde[+-]dd.
| The precision specifies the number of digits after the decimal
| point (defaulting to six).
E | Equivalent to `e', but uses an uppercase E to indicate
| the exponent.
f | Convert floating point argument as [-]ddd.dddddd,
| where the precision specifies the number of digits after
| the decimal point.
g | Convert a floating point number using exponential form
| if the exponent is less than -4 or greater than or
| equal to the precision, or in dd.dddd form otherwise.
| The precision specifies the number of significant digits.
G | Equivalent to `g', but use an uppercase `E' in exponent form.
a | Convert floating point argument as [-]0xh.hhhhp[+-]dd,
| which is consisted from optional sign, "0x", fraction part
| as hexadecimal, "p", and exponential part as decimal.
A | Equivalent to `a', but use uppercase `X' and `P'.
Field | Other Format
------+--------------------------------------------------------------
c | Argument is the numeric code for a single character or
| a single character string itself.
p | The valuing of argument.inspect.
s | Argument is a string to be substituted. If the format
| sequence contains a precision, at most that many characters
| will be copied.
% | A percent sign itself will be displayed. No argument taken. Флаги изменяют поведение форматов. Символы флагов:
Flag | Applies to | Meaning
---------+---------------+-----------------------------------------
space | bBdiouxX | Leave a space at the start of
| aAeEfgG | non-negative numbers.
| (numeric fmt) | For `o', `x', `X', `b' and `B', use
| | a minus sign with absolute value for
| | negative values.
---------+---------------+-----------------------------------------
(digit)$ | all | Specifies the absolute argument number
| | for this field. Absolute and relative
| | argument numbers cannot be mixed in a
| | sprintf string.
---------+---------------+-----------------------------------------
# | bBoxX | Use an alternative format.
| aAeEfgG | For the conversions `o', increase the precision
| | until the first digit will be `0' if
| | it is not formatted as complements.
| | For the conversions `x', `X', `b' and `B'
| | on non-zero, prefix the result with ``0x'',
| | ``0X'', ``0b'' and ``0B'', respectively.
| | For `a', `A', `e', `E', `f', `g', and 'G',
| | force a decimal point to be added,
| | even if no digits follow.
| | For `g' and 'G', do not remove trailing zeros.
---------+---------------+-----------------------------------------
+ | bBdiouxX | Add a leading plus sign to non-negative
| aAeEfgG | numbers.
| (numeric fmt) | For `o', `x', `X', `b' and `B', use
| | a minus sign with absolute value for
| | negative values.
---------+---------------+-----------------------------------------
- | all | Left-justify the result of this conversion.
---------+---------------+-----------------------------------------
0 (zero) | bBdiouxX | Pad with zeros, not spaces.
| aAeEfgG | For `o', `x', `X', `b' and `B', radix-1
| (numeric fmt) | is used for negative numbers formatted as
| | complements.
---------+---------------+-----------------------------------------
* | all | Use the next argument as the field width.
| | If negative, left-justify the result. If the
| | asterisk is followed by a number and a dollar
| | sign, use the indicated argument as the width. Примеры флагов:
# `+' and space flag specifies the sign of non-negative numbers.
sprintf("%d", 123) #=> "123"
sprintf("%+d", 123) #=> "+123"
sprintf("% d", 123) #=> " 123"
# `#' flag for `o' increases number of digits to show `0'.
# `+' and space flag changes format of negative numbers.
sprintf("%o", 123) #=> "173"
sprintf("%#o", 123) #=> "0173"
sprintf("%+o", -123) #=> "-173"
sprintf("%o", -123) #=> "..7605"
sprintf("%#o", -123) #=> "..7605"
# `#' flag for `x' add a prefix `0x' for non-zero numbers.
# `+' and space flag disables complements for negative numbers.
sprintf("%x", 123) #=> "7b"
sprintf("%#x", 123) #=> "0x7b"
sprintf("%+x", -123) #=> "-7b"
sprintf("%x", -123) #=> "..f85"
sprintf("%#x", -123) #=> "0x..f85"
sprintf("%#x", 0) #=> "0"
# `#' for `X' uses the prefix `0X'.
sprintf("%X", 123) #=> "7B"
sprintf("%#X", 123) #=> "0X7B"
# `#' flag for `b' add a prefix `0b' for non-zero numbers.
# `+' and space flag disables complements for negative numbers.
sprintf("%b", 123) #=> "1111011"
sprintf("%#b", 123) #=> "0b1111011"
sprintf("%+b", -123) #=> "-1111011"
sprintf("%b", -123) #=> "..10000101"
sprintf("%#b", -123) #=> "0b..10000101"
sprintf("%#b", 0) #=> "0"
# `#' for `B' uses the prefix `0B'.
sprintf("%B", 123) #=> "1111011"
sprintf("%#B", 123) #=> "0B1111011"
# `#' for `e' forces to show the decimal point.
sprintf("%.0e", 1) #=> "1e+00"
sprintf("%#.0e", 1) #=> "1.e+00"
# `#' for `f' forces to show the decimal point.
sprintf("%.0f", 1234) #=> "1234"
sprintf("%#.0f", 1234) #=> "1234."
# `#' for `g' forces to show the decimal point.
# It also disables stripping lowest zeros.
sprintf("%g", 123.4) #=> "123.4"
sprintf("%#g", 123.4) #=> "123.400"
sprintf("%g", 123456) #=> "123456"
sprintf("%#g", 123456) #=> "123456."
Ширина поля — это необязательное целое число, за которым необязательно следует точка и точность. Ширина определяет минимальное количество символов, которые будут записаны в результат для этого поля.
Примеры ширины:
# padding is done by spaces, width=20
# 0 or radix-1. <------------------>
sprintf("%20d", 123) #=> " 123"
sprintf("%+20d", 123) #=> " +123"
sprintf("%020d", 123) #=> "00000000000000000123"
sprintf("%+020d", 123) #=> "+0000000000000000123"
sprintf("% 020d", 123) #=> " 0000000000000000123"
sprintf("%-20d", 123) #=> "123 "
sprintf("%-+20d", 123) #=> "+123 "
sprintf("%- 20d", 123) #=> " 123 "
sprintf("%020x", -123) #=> "..ffffffffffffffff85"
Для числовых полей точность управляет количеством десятичных знаков, отображаемых. Для строковых полей точность определяет максимальное количество символов, копируемых из строки. (Таким образом, последовательность формата %10.10s всегда вносит ровно десять символов в результат.)
Примеры точности:
# precision for `d', 'o', 'x' and 'b' is
# minimum number of digits <------>
sprintf("%20.8d", 123) #=> " 00000123"
sprintf("%20.8o", 123) #=> " 00000173"
sprintf("%20.8x", 123) #=> " 0000007b"
sprintf("%20.8b", 123) #=> " 01111011"
sprintf("%20.8d", -123) #=> " -00000123"
sprintf("%20.8o", -123) #=> " ..777605"
sprintf("%20.8x", -123) #=> " ..ffff85"
sprintf("%20.8b", -11) #=> " ..110101"
# "0x" and "0b" for `#x' and `#b' is not counted for
# precision but "0" for `#o' is counted. <------>
sprintf("%#20.8d", 123) #=> " 00000123"
sprintf("%#20.8o", 123) #=> " 00000173"
sprintf("%#20.8x", 123) #=> " 0x0000007b"
sprintf("%#20.8b", 123) #=> " 0b01111011"
sprintf("%#20.8d", -123) #=> " -00000123"
sprintf("%#20.8o", -123) #=> " ..777605"
sprintf("%#20.8x", -123) #=> " 0x..ffff85"
sprintf("%#20.8b", -11) #=> " 0b..110101"
# precision for `e' is number of
# digits after the decimal point <------>
sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03"
# precision for `f' is number of
# digits after the decimal point <------>
sprintf("%20.8f", 1234.56789) #=> " 1234.56789000"
# precision for `g' is number of
# significant digits <------->
sprintf("%20.8g", 1234.56789) #=> " 1234.5679"
# <------->
sprintf("%20.8g", 123456789) #=> " 1.2345679e+08"
# precision for `s' is
# maximum number of characters <------>
sprintf("%20.8s", "string test") #=> " string t"
Примеры:
sprintf("%d %04x", 123, 123) #=> "123 007b"
sprintf("%08b '%4s'", 123, 123) #=> "01111011 ' 123'"
sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello"
sprintf("%1$*2$s %2$d", "hello", -8) #=> "hello -8"
sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23) #=> "+1.23: 1.23:1.23"
sprintf("%u", -123) #=> "-123"
Для более сложного форматирования Ruby поддерживает ссылку по имени. Стиль %<имя> использует стиль форматирования, но стиль %{имя} не использует.
Примеры:
sprintf("%<foo>d : %<bar>f", { :foo => 1, :bar => 2 })
#=> 1 : 2.000000
sprintf("%{foo}f", { :foo => 1 })
# => "1f"
# File kernel.rb, line 67 def frozen? Primitive.attr! 'inline' Primitive.cexpr! 'rb_obj_frozen_p(self)' end
Возвращает статус замораживания obj.
a = [ "a", "b", "c" ] a.freeze #=> ["a", "b", "c"] a.frozen? #=> true
static VALUE
rb_f_gets(int argc, VALUE *argv, VALUE recv)
{
if (recv == argf) {
return argf_gets(argc, argv, argf);
}
return forward(argf, idGets, argc, argv);
} Возвращает (и присваивает $_) следующую строку из списка файлов в ARGV (или $*), или со стандартного ввода, если файлы отсутствуют в командной строке. Возвращает nil в конце файла. Необязательный аргумент задаёт разделитель записей. Разделитель включается в содержимое каждой записи. Разделитель nil считывает всё содержимое, а разделитель нулевой длины считывает вход по абзацам, где абзацы разделены двумя последовательными символами новой строки. Если первый аргумент — целое число или задан необязательный второй аргумент, возвращаемая строка не будет длиннее заданного значения в байтах. Если в ARGV присутствует несколько имён файлов, gets(nil) будет считывать содержимое по одному файлу за раз.
ARGV << "testfile" print while gets
результат:
This is line one This is line two This is line three And so on...
Стиль программирования, использующий $_ в качестве неявного параметра, постепенно теряет популярность в сообществе Ruby.
static VALUE
f_global_variables(VALUE _)
{
return rb_f_global_variables();
} Возвращает массив имён глобальных переменных. Включает специальные глобальные переменные типа regexp, такие как $~ и $+, но не включает пронумерованные глобальные переменные regexp ($1, $2, и т. д.).
global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
static VALUE
rb_f_gsub(int argc, VALUE *argv, VALUE _)
{
VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("gsub"), argc, argv);
rb_lastline_set(str);
return str;
} Эквивалентно $_.gsub..., за исключением того, что $_ будет обновлён, если произойдёт подстановка. Доступно только при использовании командной строки -p/-n.
static VALUE
rb_f_iterator_p(VALUE self)
{
rb_warn_deprecated("iterator?", "block_given?");
return rb_f_block_given_p(self);
} Устарело. Используйте block_given? вместо этого.
static VALUE
rb_f_load(int argc, VALUE *argv, VALUE _)
{
VALUE fname, wrap, path, orig_fname;
rb_scan_args(argc, argv, "11", &fname, &wrap);
orig_fname = rb_get_path_check_to_string(fname);
fname = rb_str_encode_ospath(orig_fname);
RUBY_DTRACE_HOOK(LOAD_ENTRY, RSTRING_PTR(orig_fname));
path = rb_find_file(fname);
if (!path) {
if (!rb_file_load_ok(RSTRING_PTR(fname)))
load_failed(orig_fname);
path = fname;
}
rb_load_internal(path, wrap);
RUBY_DTRACE_HOOK(LOAD_RETURN, RSTRING_PTR(orig_fname));
return Qtrue;
} Загружает и выполняет Ruby-программу из файла filename.
Если имя файла — абсолютный путь (например, начинается с ‘/’), файл загружается напрямую с использованием абсолютного пути.
Если имя файла — явный относительный путь (например, начинается с ‘./’ или ‘../’), файл загружается относительно текущей директории.
В противном случае файл ищется в каталогах библиотек, указанных в $LOAD_PATH ($:). Если файл найден в каталоге, происходит попытка загрузки файла относительно этого каталога. Если файл не найден ни в одном из каталогов в $LOAD_PATH, файл загружается относительно текущей директории.
Если файла не существует при попытке загрузки, будет поднята ошибка LoadError.
Если необязательный параметр wrap равен true, загружаемый скрипт выполняется в анонимном модуле, защищая глобальное пространство имён вызывающей программы. Если необязательный параметр wrap — модуль, загружаемый скрипт выполняется в заданном модуле. Ни в каких обстоятельствах локальные переменные загруженного файла не передаются в среду загрузки.
static VALUE
rb_f_local_variables(VALUE _)
{
struct local_var_list vars;
rb_execution_context_t *ec = GET_EC();
rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp));
unsigned int i;
local_var_list_init(&vars);
while (cfp) {
if (cfp->iseq) {
for (i = 0; i < cfp->iseq->body->local_table_size; i++) {
local_var_list_add(&vars, cfp->iseq->body->local_table[i]);
}
}
if (!VM_ENV_LOCAL_P(cfp->ep)) {
/* block */
const VALUE *ep = VM_CF_PREV_EP(cfp);
if (vm_collect_local_variables_in_heap(ep, &vars)) {
break;
}
else {
while (cfp->ep != ep) {
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
}
}
else {
break;
}
}
return local_var_list_finish(&vars);
} Возвращает имена текущих локальных переменных.
fred = 1 for i in 1..10 # ... end local_variables #=> [:fred, :i]
static VALUE
rb_f_loop(VALUE self)
{
RETURN_SIZED_ENUMERATOR(self, 0, 0, rb_f_loop_size);
return rb_rescue2(loop_i, (VALUE)0, loop_stop, (VALUE)0, rb_eStopIteration, (VALUE)0);
} Повторяет выполнение блока.
Если блок не указан, возвращается итератор.
loop do print "Input: " line = gets break if !line or line =~ /^qQ/ # ... end
Исключение StopIteration, поднятое в блоке, прерывает цикл. В этом случае цикл возвращает значение «результат», сохранённое в исключении.
enum = Enumerator.new { |y|
y << "one"
y << "two"
:ok
}
result = loop {
puts enum.next
} #=> :ok
static VALUE
rb_f_open(int argc, VALUE *argv, VALUE _)
{
ID to_open = 0;
int redirect = FALSE;
if (argc >= 1) {
CONST_ID(to_open, "to_open");
if (rb_respond_to(argv[0], to_open)) {
redirect = TRUE;
}
else {
VALUE tmp = argv[0];
FilePathValue(tmp);
if (NIL_P(tmp)) {
redirect = TRUE;
}
else {
VALUE cmd = check_pipe_command(tmp);
if (!NIL_P(cmd)) {
argv[0] = cmd;
return rb_io_s_popen(argc, argv, rb_cIO);
}
}
}
}
if (redirect) {
VALUE io = rb_funcallv_kw(argv[0], to_open, argc-1, argv+1, RB_PASS_CALLED_KEYWORDS);
if (rb_block_given_p()) {
return rb_ensure(rb_yield, io, io_close, io);
}
return io;
}
return rb_io_s_open(argc, argv, rb_cFile);
} Создаёт объект IO, подключенный к заданному потоку, файлу или дочернему процессу.
Если path не начинается с символа трубы (|), рассматривается как имя файла для открытия с указанным режимом (по умолчанию — «r»).
mode — это строка или целое число. Если целое число, оно должно быть побитовым или флагов open(2), таких как File::RDWR или File::EXCL. Если строка, это либо «fmode», либо «fmode:ext_enc», либо «fmode:ext_enc:int_enc».
См. документацию IO.new для полной документации директив строки mode.
Если создаётся файл, его начальные разрешения можно задать с помощью параметра perm. См. File.new и страницы руководства open(2) и chmod(2) для описания разрешений.
Если указан блок, он будет вызван с объектом IO в качестве параметра, и объект IO будет автоматически закрыт по завершении блока. Вызов возвращает значение блока.
Если path начинается с символа трубы ("|"), создаётся дочерний процесс, подключённый к вызывающему процессу парой труб. Возвращаемый объект IO может использоваться для записи в стандартный ввод и чтения из стандартного вывода этого дочернего процесса.
Если команда после трубы — одиночный дефис ("|-"), Ruby раздваивается, и этот дочерний процесс подключается к родительскому. Если команда не "-", дочерний процесс выполняет команду. Обратите внимание, что команда может быть обработана оболочкой, если она содержит метасимволы оболочки.
Когда дочерний процесс — Ruby (открытый через "|-"), вызов open возвращает nil. Если блоку связан с вызовом open, этот блок выполнится дважды — один раз в родительском процессе и один раз в дочернем.
Параметр блока будет объектом IO в родительском процессе и nil в дочернем. Объект IO родительского процесса будет подключен к $stdin и $stdout дочернего процесса. Дочерний процесс будет завершён по окончании блока.
Примеры
Чтение из «testfile»:
open("testfile") do |f|
print f.gets
end
Результат:
This is line one
Открыть дочерний процесс и прочитать его вывод:
cmd = open("|date")
print cmd.gets
cmd.close
Результат:
Wed Apr 9 08:56:31 CDT 2003
Открыть дочерний процесс, запускающий ту же Ruby-программу:
f = open("|-", "w+")
if f.nil?
puts "in Child"
exit
else
puts "Got: #{f.gets}"
end
Результат:
Got: in Child
Открыть дочерний процесс с использованием блока для получения объекта IO:
open "|-" do |f|
if f then
# parent process
puts "Got: #{f.gets}"
else
# child process
puts "in Child"
end
end
Результат:
Got: in Child
static VALUE
rb_f_p(int argc, VALUE *argv, VALUE self)
{
int i;
for (i=0; i<argc; i++) {
VALUE inspected = rb_obj_as_string(rb_inspect(argv[i]));
rb_uninterruptible(rb_p_write, inspected);
}
return rb_p_result(argc, argv);
} Для каждого объекта напрямую выводит obj.inspect за которым следует новая строка в стандартный вывод программы.
S = Struct.new(:name, :state) s = S['dave', 'TX'] p s
результат:
#<S name="dave", state="TX">
static VALUE
rb_f_print(int argc, const VALUE *argv, VALUE _)
{
rb_io_print(argc, argv, rb_ractor_stdout());
return Qnil;
} Выводит каждый объект по очереди в $stdout. Если разделитель полей вывода ($,) не nil, его содержимое будет отображаться между каждым полем. Если разделитель записей вывода ($\) не nil, он будет добавлен в вывод. Если аргументы не указаны, выводится $_. Объекты, которые не являются строками, будут преобразованы путём вызова их метода to_s.
print "cat", [1,2,3], 99, "\n" $, = ", " $\ = "\n" print "cat", [1,2,3], 99
выводит:
cat12399 cat, 1, 2, 3, 99
static VALUE
rb_f_printf(int argc, VALUE *argv, VALUE _)
{
VALUE out;
if (argc == 0) return Qnil;
if (RB_TYPE_P(argv[0], T_STRING)) {
out = rb_ractor_stdout();
}
else {
out = argv[0];
argv++;
argc--;
}
rb_io_write(out, rb_f_sprintf(argc, argv));
return Qnil;
} Эквивалентно:
io.write(sprintf(string, obj, ...))
или
$stdout.write(sprintf(string, obj, ...))
static VALUE
f_proc(VALUE _)
{
return proc_new(rb_cProc, FALSE, TRUE);
} Эквивалентно Proc.new.
static VALUE
rb_f_putc(VALUE recv, VALUE ch)
{
VALUE r_stdout = rb_ractor_stdout();
if (recv == r_stdout) {
return rb_io_putc(recv, ch);
}
return forward(r_stdout, rb_intern("putc"), 1, &ch);
} Эквивалентно:
$stdout.putc(int)
Обратитесь к документации IO#putc за важной информацией о многобайтовых символах.
static VALUE
rb_f_puts(int argc, VALUE *argv, VALUE recv)
{
VALUE r_stdout = rb_ractor_stdout();
if (recv == r_stdout) {
return rb_io_puts(argc, argv, recv);
}
return forward(r_stdout, rb_intern("puts"), argc, argv);
} Эквивалентно
$stdout.puts(obj, ...)
static VALUE
f_raise(int c, VALUE *v, VALUE _)
{
return rb_f_raise(c, v);
} Без аргументов, генерирует исключение в $! или генерирует RuntimeError, если $! является nil. С единственным аргументом String, генерирует исключение RuntimeError с указанной строкой в качестве сообщения. В противном случае, первый параметр должен быть классом Exception (или другим объектом, возвращающим объект Exception при отправке сообщения exception). Необязательный второй параметр задаёт сообщение, связанное с исключением (доступно через Exception#message), а третий параметр — массив информации о вызове (доступно через Exception#backtrace). Причина сгенерированного исключения (доступно через Exception#cause) автоматически устанавливается на «текущее» исключение ($!), если таковое имеется. В качестве альтернативного значения, либо объект Exception, либо nil, можно указать через аргумент :cause.
Исключения обрабатываются блоком rescue в блоках begin...end.
raise "Failed to create socket" raise ArgumentError, "No parameters", caller
static VALUE
rb_f_rand(int argc, VALUE *argv, VALUE obj)
{
VALUE vmax;
rb_random_t *rnd = rand_start(default_rand());
if (rb_check_arity(argc, 0, 1) && !NIL_P(vmax = argv[0])) {
VALUE v = rand_range(obj, rnd, vmax);
if (v != Qfalse) return v;
vmax = rb_to_int(vmax);
if (vmax != INT2FIX(0)) {
v = rand_int(obj, rnd, vmax, 0);
if (!NIL_P(v)) return v;
}
}
return DBL2NUM(random_real(obj, rnd, TRUE));
} Если вызывается без аргумента или если max.to_i.abs == 0, rand возвращает псевдослучайное число с плавающей точкой между 0.0 и 1.0 включительно 0.0 и исключая 1.0.
rand #=> 0.2725926052826416
Когда max.abs больше или равно 1, rand возвращает псевдослучайное целое число, большее или равное 0 и меньшее max.to_i.abs.
rand(100) #=> 12
Когда max является Range, rand возвращает случайное число, где range.member?(number) == true.
Отрицательные или числа с плавающей точкой для max допускаются, но могут дать неожиданные результаты.
rand(-100) # => 87 rand(-0.5) # => 0.8130921818028143 rand(1.9) # equivalent to rand(1), which is always 0
Kernel.srand может использоваться для обеспечения воспроизводимости последовательностей случайных чисел в различных запусках программы.
См. также Random.rand.
static VALUE
rb_f_readline(int argc, VALUE *argv, VALUE recv)
{
if (recv == argf) {
return argf_readline(argc, argv, argf);
}
return forward(argf, rb_intern("readline"), argc, argv);
} Эквивалентно Kernel::gets, за исключением readline генерирует EOFError при достижении конца файла.
static VALUE
rb_f_readlines(int argc, VALUE *argv, VALUE recv)
{
if (recv == argf) {
return argf_readlines(argc, argv, argf);
}
return forward(argf, rb_intern("readlines"), argc, argv);
} Возвращает массив, содержащий строки, возвращённые вызовом Kernel.gets(sep) до конца файла.
VALUE
rb_f_require(VALUE obj, VALUE fname)
{
return rb_require_string(fname);
} Загружает указанный name, возвращая true при успехе и false если функция уже загружена.
Если имя файла не разрешается в абсолютный путь и не начинается с ‘./’ или ‘../’, файл будет искаться в каталогах библиотек, указанных в $LOAD_PATH ($:). Если имя файла начинается с ‘./’ или ‘../’, разрешение основано на Dir.pwd.
Если имя файла имеет расширение “.rb”, оно загружается как исходный файл; если расширение является “.so”, “.o”, или “.dll”, или стандартным расширением общих библиотек на текущей платформе, Ruby загружает общую библиотеку как расширение Ruby. В противном случае, Ruby пытается добавить “.rb”, “.so” и т.д. к имени, пока не найдёт. Если файл с заданным именем не найден, будет выброшено исключение LoadError.
Для расширений Ruby заданное имя файла может использовать любое расширение общей библиотеки. Например, в Linux расширение сокета — “socket.so”, и require 'socket.dll' загрузит расширение сокета.
Абсолютный путь загруженного файла добавляется в $LOADED_FEATURES ($"). Файл не будет загружен повторно, если его путь уже присутствует в $". Например, require 'a'; require './a' не загрузит a.rb повторно.
require "my-library.rb" require "db-driver"
Любые константы или переменные глобального уровня в загруженном исходном файле будут доступны в глобальном пространстве имен вызывающей программы. Однако локальные переменные не будут переданы в среду загрузки.
VALUE
rb_f_require_relative(VALUE obj, VALUE fname)
{
VALUE base = rb_current_realfilepath();
if (NIL_P(base)) {
rb_loaderror("cannot infer basepath");
}
base = rb_file_dirname(base);
return rb_require_string(rb_file_absolute_path(fname, base));
} Ruby пытается загрузить библиотеку с именем string относительно пути требуемого файла. Если путь к файлу не может быть определён, генерируется исключение LoadError. Если файл загружен, возвращается true, в противном случае — false.
static VALUE
rb_f_select(int argc, VALUE *argv, VALUE obj)
{
VALUE timeout;
struct select_args args;
struct timeval timerec;
int i;
rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
if (NIL_P(timeout)) {
args.timeout = 0;
}
else {
timerec = rb_time_interval(timeout);
args.timeout = &timerec;
}
for (i = 0; i < numberof(args.fdsets); ++i)
rb_fd_init(&args.fdsets[i]);
return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
} Вызывает системный вызов select(2). Отслеживает заданные массивы объектов IO, ожидает, пока один или несколько объектов IO будут готовы к чтению, будут готовы к записи и будут иметь ожидающие исключения соответственно, и возвращает массив, содержащий массивы этих объектов IO. Возвращает nil если необязательное значение timeout задано и ни один объект IO не готов в течение timeout секунд.
IO.select просматривает буфер объектов IO для проверки возможности чтения. Если буфер IO не пуст, IO.select немедленно сообщает о возможности чтения. Такое «просматривание» происходит только для объектов IO. Оно не происходит для объектов, похожих на IO, таких как OpenSSL::SSL::SSLSocket.
Лучший способ использовать IO.select — вызывать его после таких методов без блокировки, как read_nonblock, write_nonblock и т. д. Методы генерируют исключение, которое расширяется с помощью IO::WaitReadable или IO::WaitWritable. Модули сообщают, как вызывающему коду следует ожидать с помощью IO.select. Если возникает IO::WaitReadable, вызывающий код должен ждать чтения. Если возникает IO::WaitWritable, вызывающий код должен ждать записи.
Таким образом, блокирующее чтение (readpartial) можно эмулировать с помощью read_nonblock и IO.select следующим образом:
begin result = io_like.read_nonblock(maxlen) rescue IO::WaitReadable IO.select([io_like]) retry rescue IO::WaitWritable IO.select(nil, [io_like]) retry end
В особенности сочетание методов без блокировки и IO.select предпочтительнее для объектов типа IO, таких как OpenSSL::SSL::SSLSocket. У него есть метод to_io, который возвращает базовый объект IO. IO.select вызывает to_io, чтобы получить дескриптор файла для ожидания.
Это означает, что возможность чтения, оповещенная IO.select, не означает возможность чтения от объекта OpenSSL::SSL::SSLSocket.
Вероятнее всего, OpenSSL::SSL::SSLSocket буферирует некоторые данные. IO.select не видит буфера. Таким образом, IO.select может заблокироваться, когда OpenSSL::SSL::SSLSocket#readpartial не блокируется.
Однако существуют и другие более сложные ситуации.
SSL — это протокол, который представляет собой последовательность записей. Запись состоит из нескольких байтов. Таким образом, удалённая сторона SSL отправляет частичную запись, IO.select сообщает о возможности чтения, но OpenSSL::SSL::SSLSocket не может расшифровать байт, и OpenSSL::SSL::SSLSocket#readpartial заблокируется.
Кроме того, удалённая сторона может запросить повторное согласование SSL, которое заставляет локальный движок SSL записать некоторые данные. Это означает, что OpenSSL::SSL::SSLSocket#readpartial может вызвать системный вызов записи, и он может заблокироваться. В такой ситуации OpenSSL::SSL::SSLSocket#read_nonblock генерирует IO::WaitWritable вместо блокировки. Таким образом, вызывающий код должен ждать готовности к записи, как в примере выше.
Сочетание методов без блокировки и IO.select также полезно для потоков, таких как tty, сокеты каналов и сокеты, когда несколько процессов читают из потока.
Наконец, разработчики ядра Linux не гарантируют, что возможность чтения select(2) означает возможность чтения последующего read(2) даже для одного процесса. Обратитесь к руководству select(2) на системе GNU/Linux.
Вызов IO.select до IO#readpartial работает нормально, как обычно. Однако это не лучший способ использования IO.select.
Оповещение о возможности записи select(2) не показывает, сколько байтов можно записать. Метод IO#write блокируется, пока вся заданная строка не будет записана. Таким образом, IO#write(two or more bytes) может заблокироваться после оповещения о возможности записи IO.select. Необходимо использовать IO#write_nonblock, чтобы избежать блокировки.
Блокирующая запись (write) можно эмулировать с помощью write_nonblock и IO.select следующим образом: IO::WaitReadable также необходимо перехватывать для повторного согласования SSL в OpenSSL::SSL::SSLSocket.
while 0 < string.bytesize
begin
written = io_like.write_nonblock(string)
rescue IO::WaitReadable
IO.select([io_like])
retry
rescue IO::WaitWritable
IO.select(nil, [io_like])
retry
end
string = string.byteslice(written..-1)
end
Параметры
- read_array
-
массив объектов
IO, которые ожидают готовности к чтению - write_array
-
массив объектов
IO, которые ожидают готовности к записи - error_array
-
массив объектов
IO, которые ожидают исключений - timeout
-
числовое значение в секундах
Пример
rp, wp = IO.pipe
mesg = "ping "
100.times {
# IO.select follows IO#read. Not the best way to use IO.select.
rs, ws, = IO.select([rp], [wp])
if r = rs[0]
ret = r.read(5)
print ret
case ret
when /ping/
mesg = "pong\n"
when /pong/
mesg = "ping "
end
end
if w = ws[0]
w.write(mesg)
end
}
выводит:
ping pong ping pong ping pong (snipped) ping
static VALUE
set_trace_func(VALUE obj, VALUE trace)
{
rb_remove_event_hook(call_trace_func);
if (NIL_P(trace)) {
return Qnil;
}
if (!rb_obj_is_proc(trace)) {
rb_raise(rb_eTypeError, "trace_func needs to be Proc");
}
rb_add_event_hook(call_trace_func, RUBY_EVENT_ALL, trace);
return trace;
} Establishes _proc_ as the handler for tracing, or disables
tracing if the parameter is +nil+.
*Note:* this method is obsolete, please use TracePoint instead.
_proc_ takes up to six parameters:
* an event name
* a filename
* a line number
* an object id
* a binding
* the name of a class
_proc_ is invoked whenever an event occurs.
Events are:
+c-call+:: call a C-language routine
+c-return+:: return from a C-language routine
+call+:: call a Ruby method
+class+:: start a class or module definition
+end+:: finish a class or module definition
+line+:: execute code on a new line
+raise+:: raise an exception
+return+:: return from a Ruby method
Tracing is disabled within the context of _proc_.
class Test
def test
a = 1
b = 2
end
end
set_trace_func proc { |event, file, line, id, binding, classname|
printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}
t = Test.new
t.test
line prog.rb:11 false
c-call prog.rb:11 new Class
c-call prog.rb:11 initialize Object
c-return prog.rb:11 initialize Object
c-return prog.rb:11 new Class
line prog.rb:12 false
call prog.rb:2 test Test
line prog.rb:3 test Test
line prog.rb:4 test Test
return prog.rb:4 test Test Обратите внимание, что для событий c-call и c-return возвращаемая привязка — это привязка ближайшего метода Ruby, вызывающего C-метод, так как у самих C-методов нет привязок.
static VALUE
rb_f_sleep(int argc, VALUE *argv, VALUE _)
{
time_t beg = time(0);
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
rb_fiber_scheduler_kernel_sleepv(scheduler, argc, argv);
}
else {
if (argc == 0) {
rb_thread_sleep_forever();
}
else {
rb_check_arity(argc, 0, 1);
rb_thread_wait_for(rb_time_interval(argv[0]));
}
}
time_t end = time(0) - beg;
return TIMET2NUM(end);
} Приостанавливает текущую нить на duration секунд (что может быть любым числом, включая Float с дробными секундами). Возвращает фактическое количество проспанных секунд (округлённое), которое может быть меньше запрошенного, если другая нить вызовет Thread#run. При вызове без аргумента, sleep() будет ждать вечно.
Time.new #=> 2008-03-08 19:56:19 +0900 sleep 1.2 #=> 1 Time.new #=> 2008-03-08 19:56:20 +0900 sleep 1.9 #=> 2 Time.new #=> 2008-03-08 19:56:22 +0900
static VALUE
rb_f_spawn(int argc, VALUE *argv, VALUE _)
{
rb_pid_t pid;
char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
VALUE execarg_obj, fail_str;
struct rb_execarg *eargp;
execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
eargp = rb_execarg_get(execarg_obj);
fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
pid = rb_execarg_spawn(execarg_obj, errmsg, sizeof(errmsg));
if (pid == -1) {
int err = errno;
rb_exec_fail(eargp, err, errmsg);
RB_GC_GUARD(execarg_obj);
rb_syserr_fail_str(err, fail_str);
}
#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
return PIDT2NUM(pid);
#else
return Qnil;
#endif
} spawn выполняет указанную команду и возвращает её pid.
pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pid
pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid
Этот метод похож на Kernel#system, но не ожидает завершения команды.
Родительский процесс должен использовать Process.wait для получения статуса завершения своего дочернего процесса или использовать Process.detach для отказа от интереса к его статусу; в противном случае операционная система может накапливать процессы-зомби.
spawn имеет набор опций для задания атрибутов процесса:
env: hash
name => val : set the environment variable
name => nil : unset the environment variable
the keys and the values except for +nil+ must be strings.
command...:
commandline : command line string which is passed to the standard shell
cmdname, arg1, ... : command name and one or more arguments (This form does not use the shell. See below for caveats.)
[cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
clearing environment variables:
:unsetenv_others => true : clear environment variables except specified by env
:unsetenv_others => false : don't clear (default)
process group:
:pgroup => true or 0 : make a new process group
:pgroup => pgid : join the specified process group
:pgroup => nil : don't change the process group (default)
create new process group: Windows only
:new_pgroup => true : the new process is the root process of a new process group
:new_pgroup => false : don't create a new process group (default)
resource limit: resourcename is core, cpu, data, etc. See Process.setrlimit.
:rlimit_resourcename => limit
:rlimit_resourcename => [cur_limit, max_limit]
umask:
:umask => int
redirection:
key:
FD : single file descriptor in child process
[FD, FD, ...] : multiple file descriptor in child process
value:
FD : redirect to the file descriptor in parent process
string : redirect to file with open(string, "r" or "w")
[string] : redirect to file with open(string, File::RDONLY)
[string, open_mode] : redirect to file with open(string, open_mode, 0644)
[string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
[:child, FD] : redirect to the redirected file descriptor
:close : close the file descriptor in child process
FD is one of follows
:in : the file descriptor 0 which is the standard input
:out : the file descriptor 1 which is the standard output
:err : the file descriptor 2 which is the standard error
integer : the file descriptor of specified the integer
io : the file descriptor specified as io.fileno
file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
:close_others => false : inherit
current directory:
:chdir => str Форма cmdname, arg1, ... не использует оболочку. Однако на разных ОС разные вещи предоставляются в качестве встроенных команд. Пример — +‘echo’+, который является встроенной командой в Windows, но обычной программой в Linux и Mac OS X. Это означает, что Process.spawn 'echo', '%Path%' отобразит содержимое переменной среды %Path% в Windows, а Process.spawn 'echo', '$PATH' напечатает буквально $PATH.
Если в качестве env передаётся хэш, то среда обновляется env перед exec(2) в дочернем процессе. Если в паре env значение равно nil, то переменная удаляется.
# set FOO as BAR and unset BAZ.
pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)
Если в качестве options передаётся хэш, он задаёт группу процессов, создание новой группы процессов, лимиты ресурсов, текущую директорию, umask и перенаправления для дочернего процесса. Также может быть задано очищение переменных среды.
Ключ :unsetenv_others в options указывает на очищение переменных среды, кроме тех, которые заданы env.
pid = spawn(command, :unsetenv_others=>true) # no environment variable
pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only
Ключ :pgroup в options задаёт группу процессов. Соответствующее значение должно быть true, нулём, положительным целым числом или nil. true и ноль делают процесс лидером новой группы процессов. Положительное целое число отличное от нуля заставляет процесс присоединиться к указанной группе. По умолчанию, nil, процесс остаётся в той же группе.
pid = spawn(command, :pgroup=>true) # process leader pid = spawn(command, :pgroup=>10) # belongs to the process group 10
Ключ :new_pgroup в options указывает на передачу флага CREATE_NEW_PROCESS_GROUP в CreateProcessW() (API Windows). Эта опция только для Windows. true означает, что новый процесс является корневым процессом новой группы процессов. У нового процесса отключено CTRL+C. Этот флаг необходим для Process.kill(:SIGINT, pid) в дочернем процессе. :new_pgroup по умолчанию false.
pid = spawn(command, :new_pgroup=>true) # new process group pid = spawn(command, :new_pgroup=>false) # same process group
Ключ :rlimit_foo указывает на лимит ресурса. foo должен быть одним из типов ресурсов, таких как core. Соответствующее значение должно быть целым числом или массивом, содержащим одно или два целых числа: аналогично аргументам cur_limit и max_limit для Process.setrlimit.
cur, max = Process.getrlimit(:CORE) pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary. pid = spawn(command, :rlimit_core=>max) # enable core dump pid = spawn(command, :rlimit_core=>0) # never dump core.
Ключ :umask в options указывает umask.
pid = spawn(command, :umask=>077)
Ключи :in, :out, :err, целое число, IO и массив задают перенаправление. Перенаправление сопоставляет дескриптор файла в дочернем процессе.
Например, stderr можно объединить с stdout следующим образом:
pid = spawn(command, :err=>:out) pid = spawn(command, 2=>1) pid = spawn(command, STDERR=>:out) pid = spawn(command, STDERR=>STDOUT)
Ключи хэша задают дескриптор файла в дочернем процессе, запущенном с помощью spawn. :err, 2 и STDERR указывают поток стандартной ошибки (stderr).
Значения хэша задают дескриптор файла в родительском процессе, который вызывает spawn. :out, 1 и STDOUT указывают поток стандартного вывода (stdout).
В приведённом примере стандартный вывод в дочернем процессе не указан. Поэтому он наследуется от родительского процесса.
Поток стандартного ввода (stdin) можно задать с помощью :in, 0 и STDIN.
Можно указать имя файла в качестве значения хэша.
pid = spawn(command, :in=>"/dev/null") # read mode pid = spawn(command, :out=>"/dev/null") # write mode pid = spawn(command, :err=>"log") # write mode pid = spawn(command, [:out, :err]=>"/dev/null") # write mode pid = spawn(command, 3=>"/dev/null") # read mode
Для stdout и stderr (и их комбинации) открывается режим записи. В противном случае используется режим чтения.
Для явного задания флагов и прав создания файла используется массив.
pid = spawn(command, :in=>["file"]) # read mode is assumed pid = spawn(command, :in=>["file", "r"]) pid = spawn(command, :out=>["log", "w"]) # 0644 assumed pid = spawn(command, :out=>["log", "w", 0600]) pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])
Массив задаёт имя файла, флаги и права. Флаги могут быть строкой или целым числом. Если флаги отсутствуют или nil, предполагается File::RDONLY. Права должны быть целым числом. Если права отсутствуют или nil, предполагается 0644.
Если в качестве ключа хэша указан массив IOs и целых чисел, все элементы перенаправляются.
# stdout and stderr is redirected to log file. # The file "log" is opened just once. pid = spawn(command, [:out, :err]=>["log", "w"])
Другой способ объединения нескольких дескрипторов — [:child, fd]. [:child, fd] означает дескриптор файла в дочернем процессе. Это отличается от fd. Например, :err=>:out означает перенаправление stderr дочернего процесса в stdout родительского процесса. А :err=>[:child, :out] означает перенаправление stderr дочернего процесса в stdout дочернего процесса. Разница проявляется, если stdout перенаправляется в дочернем процессе, как показано ниже.
# stdout and stderr is redirected to log file. # The file "log" is opened just once. pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])
[:child, :out] можно использовать для объединения stderr в stdout в IO.popen. В этом случае, IO.popen перенаправляет stdout в канал в дочернем процессе, а [:child, :out] относится к перенаправленному stdout.
io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]]) p io.read #=> "out\nerr\n"
Ключ :chdir в options указывает текущую директорию.
pid = spawn(command, :chdir=>"/var/tmp")
spawn по умолчанию закрывает все нестандартные неуказанные дескрипторы. «Стандартные» дескрипторы — 0, 1 и 2. Это поведение задаётся опцией :close_others. :close_others не влияет на стандартные дескрипторы, которые закрываются только если :close указан явно.
pid = spawn(command, :close_others=>true) # close 3,4,5,... (default) pid = spawn(command, :close_others=>false) # don't close 3,4,5,...
:close_others по умолчанию false для spawn и IO.popen.
Обратите внимание, что дескрипторы, у которых установлен флаг close-on-exec, закрываются независимо от опции :close_others.
Поэтому IO.pipe и spawn могут использоваться как IO.popen.
# similar to r = IO.popen(command) r, w = IO.pipe pid = spawn(command, :out=>w) # r, w is closed in the child process. w.close
:close задаётся как значение хэша для отдельного закрытия дескриптора.
f = open(foo) system(command, f=>:close) # don't inherit f.
Если дескриптор файла нужно унаследовать, можно использовать io=>io.
# valgrind has --log-fd option for log destination.
# log_w=>log_w indicates log_w.fileno inherits to child process.
log_r, log_w = IO.pipe
pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
log_w.close
p log_r.read
Также возможно обмен дескрипторами файлов.
pid = spawn(command, :out=>:err, :err=>:out)
Ключи хэша задают дескрипторы файлов в дочернем процессе, значения — в родительском. Таким образом, выше показано перенаправление stdout и stderr. Внутри spawn используется дополнительный дескриптор для разрешения таких циклических сопоставлений дескрипторов файлов.
См. Kernel.exec для стандартной оболочки.
static VALUE
f_sprintf(int c, const VALUE *v, VALUE _)
{
return rb_f_sprintf(c, v);
} Возвращает строку, полученную в результате применения format_string к дополнительным аргументам. Внутри строки форматирования любые символы, отличные от последовательностей форматирования, копируются в результат.
Синтаксис последовательности форматирования:
%[flags][width][.precision]type
Последовательность форматирования состоит из знака процента, за которым следуют необязательные флаги, ширина и точность, а затем — символ типа поля. Тип поля определяет, как соответствующий sprintf аргумент будет интерпретироваться, а флаги изменяют эту интерпретацию.
Символы типа поля:
Field | Integer Format
------+--------------------------------------------------------------
b | Convert argument as a binary number.
| Negative numbers will be displayed as a two's complement
| prefixed with `..1'.
B | Equivalent to `b', but uses an uppercase 0B for prefix
| in the alternative format by #.
d | Convert argument as a decimal number.
i | Identical to `d'.
o | Convert argument as an octal number.
| Negative numbers will be displayed as a two's complement
| prefixed with `..7'.
u | Identical to `d'.
x | Convert argument as a hexadecimal number.
| Negative numbers will be displayed as a two's complement
| prefixed with `..f' (representing an infinite string of
| leading 'ff's).
X | Equivalent to `x', but uses uppercase letters.
Field | Float Format
------+--------------------------------------------------------------
e | Convert floating point argument into exponential notation
| with one digit before the decimal point as [-]d.dddddde[+-]dd.
| The precision specifies the number of digits after the decimal
| point (defaulting to six).
E | Equivalent to `e', but uses an uppercase E to indicate
| the exponent.
f | Convert floating point argument as [-]ddd.dddddd,
| where the precision specifies the number of digits after
| the decimal point.
g | Convert a floating point number using exponential form
| if the exponent is less than -4 or greater than or
| equal to the precision, or in dd.dddd form otherwise.
| The precision specifies the number of significant digits.
G | Equivalent to `g', but use an uppercase `E' in exponent form.
a | Convert floating point argument as [-]0xh.hhhhp[+-]dd,
| which is consisted from optional sign, "0x", fraction part
| as hexadecimal, "p", and exponential part as decimal.
A | Equivalent to `a', but use uppercase `X' and `P'.
Field | Other Format
------+--------------------------------------------------------------
c | Argument is the numeric code for a single character or
| a single character string itself.
p | The valuing of argument.inspect.
s | Argument is a string to be substituted. If the format
| sequence contains a precision, at most that many characters
| will be copied.
% | A percent sign itself will be displayed. No argument taken. Флаги изменяют поведение форматов. Символы флагов:
Flag | Applies to | Meaning
---------+---------------+-----------------------------------------
space | bBdiouxX | Leave a space at the start of
| aAeEfgG | non-negative numbers.
| (numeric fmt) | For `o', `x', `X', `b' and `B', use
| | a minus sign with absolute value for
| | negative values.
---------+---------------+-----------------------------------------
(digit)$ | all | Specifies the absolute argument number
| | for this field. Absolute and relative
| | argument numbers cannot be mixed in a
| | sprintf string.
---------+---------------+-----------------------------------------
# | bBoxX | Use an alternative format.
| aAeEfgG | For the conversions `o', increase the precision
| | until the first digit will be `0' if
| | it is not formatted as complements.
| | For the conversions `x', `X', `b' and `B'
| | on non-zero, prefix the result with ``0x'',
| | ``0X'', ``0b'' and ``0B'', respectively.
| | For `a', `A', `e', `E', `f', `g', and 'G',
| | force a decimal point to be added,
| | even if no digits follow.
| | For `g' and 'G', do not remove trailing zeros.
---------+---------------+-----------------------------------------
+ | bBdiouxX | Add a leading plus sign to non-negative
| aAeEfgG | numbers.
| (numeric fmt) | For `o', `x', `X', `b' and `B', use
| | a minus sign with absolute value for
| | negative values.
---------+---------------+-----------------------------------------
- | all | Left-justify the result of this conversion.
---------+---------------+-----------------------------------------
0 (zero) | bBdiouxX | Pad with zeros, not spaces.
| aAeEfgG | For `o', `x', `X', `b' and `B', radix-1
| (numeric fmt) | is used for negative numbers formatted as
| | complements.
---------+---------------+-----------------------------------------
* | all | Use the next argument as the field width.
| | If negative, left-justify the result. If the
| | asterisk is followed by a number and a dollar
| | sign, use the indicated argument as the width. Примеры флагов:
# `+' and space flag specifies the sign of non-negative numbers.
sprintf("%d", 123) #=> "123"
sprintf("%+d", 123) #=> "+123"
sprintf("% d", 123) #=> " 123"
# `#' flag for `o' increases number of digits to show `0'.
# `+' and space flag changes format of negative numbers.
sprintf("%o", 123) #=> "173"
sprintf("%#o", 123) #=> "0173"
sprintf("%+o", -123) #=> "-173"
sprintf("%o", -123) #=> "..7605"
sprintf("%#o", -123) #=> "..7605"
# `#' flag for `x' add a prefix `0x' for non-zero numbers.
# `+' and space flag disables complements for negative numbers.
sprintf("%x", 123) #=> "7b"
sprintf("%#x", 123) #=> "0x7b"
sprintf("%+x", -123) #=> "-7b"
sprintf("%x", -123) #=> "..f85"
sprintf("%#x", -123) #=> "0x..f85"
sprintf("%#x", 0) #=> "0"
# `#' for `X' uses the prefix `0X'.
sprintf("%X", 123) #=> "7B"
sprintf("%#X", 123) #=> "0X7B"
# `#' flag for `b' add a prefix `0b' for non-zero numbers.
# `+' and space flag disables complements for negative numbers.
sprintf("%b", 123) #=> "1111011"
sprintf("%#b", 123) #=> "0b1111011"
sprintf("%+b", -123) #=> "-1111011"
sprintf("%b", -123) #=> "..10000101"
sprintf("%#b", -123) #=> "0b..10000101"
sprintf("%#b", 0) #=> "0"
# `#' for `B' uses the prefix `0B'.
sprintf("%B", 123) #=> "1111011"
sprintf("%#B", 123) #=> "0B1111011"
# `#' for `e' forces to show the decimal point.
sprintf("%.0e", 1) #=> "1e+00"
sprintf("%#.0e", 1) #=> "1.e+00"
# `#' for `f' forces to show the decimal point.
sprintf("%.0f", 1234) #=> "1234"
sprintf("%#.0f", 1234) #=> "1234."
# `#' for `g' forces to show the decimal point.
# It also disables stripping lowest zeros.
sprintf("%g", 123.4) #=> "123.4"
sprintf("%#g", 123.4) #=> "123.400"
sprintf("%g", 123456) #=> "123456"
sprintf("%#g", 123456) #=> "123456."
Ширина поля — это необязательное целое число, за которым необязательно следует точка и точность. Ширина задаёт минимальное количество символов, которое будет записано в результат для этого поля.
Примеры ширины:
# padding is done by spaces, width=20
# 0 or radix-1. <------------------>
sprintf("%20d", 123) #=> " 123"
sprintf("%+20d", 123) #=> " +123"
sprintf("%020d", 123) #=> "00000000000000000123"
sprintf("%+020d", 123) #=> "+0000000000000000123"
sprintf("% 020d", 123) #=> " 0000000000000000123"
sprintf("%-20d", 123) #=> "123 "
sprintf("%-+20d", 123) #=> "+123 "
sprintf("%- 20d", 123) #=> " 123 "
sprintf("%020x", -123) #=> "..ffffffffffffffff85"
Для числовых полей точность контролирует количество десятичных знаков. Для строковых полей точность определяет максимальное количество символов, которые будут скопированы из строки. (Таким образом, последовательность форматирования %10.10s всегда внесёт ровно десять символов в результат.)
Примеры точностей:
# precision for `d', 'o', 'x' and 'b' is
# minimum number of digits <------>
sprintf("%20.8d", 123) #=> " 00000123"
sprintf("%20.8o", 123) #=> " 00000173"
sprintf("%20.8x", 123) #=> " 0000007b"
sprintf("%20.8b", 123) #=> " 01111011"
sprintf("%20.8d", -123) #=> " -00000123"
sprintf("%20.8o", -123) #=> " ..777605"
sprintf("%20.8x", -123) #=> " ..ffff85"
sprintf("%20.8b", -11) #=> " ..110101"
# "0x" and "0b" for `#x' and `#b' is not counted for
# precision but "0" for `#o' is counted. <------>
sprintf("%#20.8d", 123) #=> " 00000123"
sprintf("%#20.8o", 123) #=> " 00000173"
sprintf("%#20.8x", 123) #=> " 0x0000007b"
sprintf("%#20.8b", 123) #=> " 0b01111011"
sprintf("%#20.8d", -123) #=> " -00000123"
sprintf("%#20.8o", -123) #=> " ..777605"
sprintf("%#20.8x", -123) #=> " 0x..ffff85"
sprintf("%#20.8b", -11) #=> " 0b..110101"
# precision for `e' is number of
# digits after the decimal point <------>
sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03"
# precision for `f' is number of
# digits after the decimal point <------>
sprintf("%20.8f", 1234.56789) #=> " 1234.56789000"
# precision for `g' is number of
# significant digits <------->
sprintf("%20.8g", 1234.56789) #=> " 1234.5679"
# <------->
sprintf("%20.8g", 123456789) #=> " 1.2345679e+08"
# precision for `s' is
# maximum number of characters <------>
sprintf("%20.8s", "string test") #=> " string t"
Примеры:
sprintf("%d %04x", 123, 123) #=> "123 007b"
sprintf("%08b '%4s'", 123, 123) #=> "01111011 ' 123'"
sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello"
sprintf("%1$*2$s %2$d", "hello", -8) #=> "hello -8"
sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23) #=> "+1.23: 1.23:1.23"
sprintf("%u", -123) #=> "-123"
Для более сложного форматирования Ruby поддерживает ссылку по имени. Стиль %<name>s использует стиль форматирования, а %{name} — нет.
Примеры:
sprintf("%<foo>d : %<bar>f", { :foo => 1, :bar => 2 })
#=> 1 : 2.000000
sprintf("%{foo}f", { :foo => 1 })
# => "1f"
static VALUE
rb_f_srand(int argc, VALUE *argv, VALUE obj)
{
VALUE seed, old;
rb_random_mt_t *r = rand_mt_start(default_rand());
if (rb_check_arity(argc, 0, 1) == 0) {
seed = random_seed(obj);
}
else {
seed = rb_to_int(argv[0]);
}
old = r->base.seed;
rand_init(&random_mt_if, &r->base, seed);
r->base.seed = seed;
return old;
} Инициализирует генератор псевдослучайных чисел системы с number. Возвращается предыдущее значение seed.
Если number опущено, генератор инициализируется с использованием источника энтропии, предоставляемого операционной системой (если доступно — /dev/urandom на Unix-системах или криптографический провайдер RSA на Windows), который затем объединяется со временем, идентификатором процесса и номером последовательности.
srand можно использовать для обеспечения повторяемости последовательностей псевдослучайных чисел при разных запусках программы. Установив seed на известное значение, можно сделать программы детерминированными во время тестирования.
srand 1234 # => 268519324636777531569100071560086917274 [ rand, rand ] # => [0.1915194503788923, 0.6221087710398319] [ rand(10), rand(1000) ] # => [4, 664] srand 1234 # => 1234 [ rand, rand ] # => [0.1915194503788923, 0.6221087710398319]
static VALUE
rb_f_sub(int argc, VALUE *argv, VALUE _)
{
VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("sub"), argc, argv);
rb_lastline_set(str);
return str;
} Эквивалентно $_.sub(args), за исключением того, что $_ будет обновлён, если произойдёт подстановка. Доступно только при использовании опций -p/-n командной строки.
static VALUE
rb_f_syscall(int argc, VALUE *argv, VALUE _)
{
VALUE arg[8];
#if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
# define SYSCALL __syscall
# define NUM2SYSCALLID(x) NUM2LONG(x)
# define RETVAL2NUM(x) LONG2NUM(x)
# if SIZEOF_LONG == 8
long num, retval = -1;
# elif SIZEOF_LONG_LONG == 8
long long num, retval = -1;
# else
# error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
# endif
#elif defined(__linux__)
# define SYSCALL syscall
# define NUM2SYSCALLID(x) NUM2LONG(x)
# define RETVAL2NUM(x) LONG2NUM(x)
/*
* Linux man page says, syscall(2) function prototype is below.
*
* int syscall(int number, ...);
*
* But, it's incorrect. Actual one takes and returned long. (see unistd.h)
*/
long num, retval = -1;
#else
# define SYSCALL syscall
# define NUM2SYSCALLID(x) NUM2INT(x)
# define RETVAL2NUM(x) INT2NUM(x)
int num, retval = -1;
#endif
int i;
if (RTEST(ruby_verbose)) {
rb_category_warning(RB_WARN_CATEGORY_DEPRECATED,
"We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
}
if (argc == 0)
rb_raise(rb_eArgError, "too few arguments for syscall");
if (argc > numberof(arg))
rb_raise(rb_eArgError, "too many arguments for syscall");
num = NUM2SYSCALLID(argv[0]); ++argv;
for (i = argc - 1; i--; ) {
VALUE v = rb_check_string_type(argv[i]);
if (!NIL_P(v)) {
SafeStringValue(v);
rb_str_modify(v);
arg[i] = (VALUE)StringValueCStr(v);
}
else {
arg[i] = (VALUE)NUM2LONG(argv[i]);
}
}
switch (argc) {
case 1:
retval = SYSCALL(num);
break;
case 2:
retval = SYSCALL(num, arg[0]);
break;
case 3:
retval = SYSCALL(num, arg[0],arg[1]);
break;
case 4:
retval = SYSCALL(num, arg[0],arg[1],arg[2]);
break;
case 5:
retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
break;
case 6:
retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
break;
case 7:
retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
break;
case 8:
retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
break;
}
if (retval == -1)
rb_sys_fail(0);
return RETVAL2NUM(retval);
#undef SYSCALL
#undef NUM2SYSCALLID
#undef RETVAL2NUM
} Вызывает функцию операционной системы, идентифицированную по num, и возвращает результат функции или вызывает SystemCallError, если произошла ошибка.
Аргументы для функции могут следовать за num. Они должны быть объектами String или Integer. Объект String передаётся как указатель на байтовую последовательность. Объект Integer передаётся как целое число, размер которого в битах совпадает с размером указателя. Можно передать до девяти параметров.
Функция, идентифицированная по num, зависит от системы. В некоторых Unix-системах номера можно получить из заголовочного файла под названием syscall.h.
syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
Результат:
hello
Вызов syscall на платформе, которая не имеет возможности вызова произвольной системной функции, просто завершается с ошибкой NotImplementedError.
Примечание: syscall по сути небезопасен и не переносим. Можете спокойно «наступать на грабли». Библиотека DL (Fiddle) предпочтительнее для более безопасного и немного более переносимого программирования.
static VALUE
rb_f_system(int argc, VALUE *argv, VALUE _)
{
VALUE execarg_obj = rb_execarg_new(argc, argv, TRUE, TRUE);
struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
struct rb_process_status status = {0};
eargp->status = &status;
rb_last_status_clear();
// This function can set the thread's last status.
// May be different from waitpid_state.pid on exec failure.
rb_pid_t pid = rb_execarg_spawn(execarg_obj, 0, 0);
if (pid > 0) {
VALUE status = rb_process_status_wait(pid, 0);
struct rb_process_status *data = RTYPEDDATA_DATA(status);
// Set the last status:
rb_obj_freeze(status);
GET_THREAD()->last_status = status;
if (data->status == EXIT_SUCCESS) {
return Qtrue;
}
if (data->error != 0) {
if (eargp->exception) {
VALUE command = eargp->invoke.sh.shell_script;
RB_GC_GUARD(execarg_obj);
rb_syserr_fail_str(data->error, command);
}
else {
return Qnil;
}
}
else if (eargp->exception) {
VALUE command = eargp->invoke.sh.shell_script;
VALUE str = rb_str_new_cstr("Command failed with");
rb_str_cat_cstr(pst_message_status(str, data->status), ": ");
rb_str_append(str, command);
RB_GC_GUARD(execarg_obj);
rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, str));
}
else {
return Qfalse;
}
RB_GC_GUARD(status);
}
if (eargp->exception) {
VALUE command = eargp->invoke.sh.shell_script;
RB_GC_GUARD(execarg_obj);
rb_syserr_fail_str(errno, command);
}
else {
return Qnil;
}
} Выполняет command… во вспомогательной оболочке. command… имеет одну из следующих форм.
-
commandline -
Строка командной строки, передаваемая в стандартную оболочку
-
cmdname, arg1, ... -
Имя команды и один или более аргументов (без оболочки)
-
[cmdname, argv0], arg1, ... -
Имя команды,
argv[0]и ноль или более аргументов (без оболочки)
system возвращает true, если команда завершается с нулевым кодом возврата, false — для ненулевого кода возврата. Возвращает nil, если выполнение команды завершается с ошибкой. Код ошибки доступен в $?.
Если передан аргумент exception: true, метод вызывает исключение вместо возвращения false или nil.
Аргументы обрабатываются так же, как и для Kernel#spawn.
Хэш-аргументы env и options такие же, как у exec и spawn. Подробнее см. Kernel#spawn.
system("echo *")
system("echo", "*")
Результат:
config.h main.rb *
Обработка ошибок:
system("cat nonexistent.txt")
# => false
system("catt nonexistent.txt")
# => nil
system("cat nonexistent.txt", exception: true)
# RuntimeError (Command failed with exit 1: cat)
system("catt nonexistent.txt", exception: true)
# Errno::ENOENT (No such file or directory - catt)
См. Kernel#exec для стандартной оболочки.
# File kernel.rb, line 89 def tap yield(self) self end
Передаёт self в блок, а затем возвращает self. Основное назначение этого метода — «подключиться» к цепочке методов для выполнения операций над промежуточными результатами в цепочке.
(1..10) .tap {|x| puts "original: #{x}" }
.to_a .tap {|x| puts "array: #{x}" }
.select {|x| x.even? } .tap {|x| puts "evens: #{x}" }
.map {|x| x*x } .tap {|x| puts "squares: #{x}" }
static VALUE
rb_f_test(int argc, VALUE *argv, VALUE _)
{
int cmd;
if (argc == 0) rb_check_arity(argc, 2, 3);
cmd = NUM2CHR(argv[0]);
if (cmd == 0) {
goto unknown;
}
if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
CHECK(1);
switch (cmd) {
case 'b':
return rb_file_blockdev_p(0, argv[1]);
case 'c':
return rb_file_chardev_p(0, argv[1]);
case 'd':
return rb_file_directory_p(0, argv[1]);
case 'e':
return rb_file_exist_p(0, argv[1]);
case 'f':
return rb_file_file_p(0, argv[1]);
case 'g':
return rb_file_sgid_p(0, argv[1]);
case 'G':
return rb_file_grpowned_p(0, argv[1]);
case 'k':
return rb_file_sticky_p(0, argv[1]);
case 'l':
return rb_file_symlink_p(0, argv[1]);
case 'o':
return rb_file_owned_p(0, argv[1]);
case 'O':
return rb_file_rowned_p(0, argv[1]);
case 'p':
return rb_file_pipe_p(0, argv[1]);
case 'r':
return rb_file_readable_p(0, argv[1]);
case 'R':
return rb_file_readable_real_p(0, argv[1]);
case 's':
return rb_file_size_p(0, argv[1]);
case 'S':
return rb_file_socket_p(0, argv[1]);
case 'u':
return rb_file_suid_p(0, argv[1]);
case 'w':
return rb_file_writable_p(0, argv[1]);
case 'W':
return rb_file_writable_real_p(0, argv[1]);
case 'x':
return rb_file_executable_p(0, argv[1]);
case 'X':
return rb_file_executable_real_p(0, argv[1]);
case 'z':
return rb_file_zero_p(0, argv[1]);
}
}
if (strchr("MAC", cmd)) {
struct stat st;
VALUE fname = argv[1];
CHECK(1);
if (rb_stat(fname, &st) == -1) {
int e = errno;
FilePathValue(fname);
rb_syserr_fail_path(e, fname);
}
switch (cmd) {
case 'A':
return stat_atime(&st);
case 'M':
return stat_mtime(&st);
case 'C':
return stat_ctime(&st);
}
}
if (cmd == '-') {
CHECK(2);
return rb_file_identical_p(0, argv[1], argv[2]);
}
if (strchr("=<>", cmd)) {
struct stat st1, st2;
struct timespec t1, t2;
CHECK(2);
if (rb_stat(argv[1], &st1) < 0) return Qfalse;
if (rb_stat(argv[2], &st2) < 0) return Qfalse;
t1 = stat_mtimespec(&st1);
t2 = stat_mtimespec(&st2);
switch (cmd) {
case '=':
if (t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec) return Qtrue;
return Qfalse;
case '>':
if (t1.tv_sec > t2.tv_sec) return Qtrue;
if (t1.tv_sec == t2.tv_sec && t1.tv_nsec > t2.tv_nsec) return Qtrue;
return Qfalse;
case '<':
if (t1.tv_sec < t2.tv_sec) return Qtrue;
if (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec) return Qtrue;
return Qfalse;
}
}
unknown:
/* unknown command */
if (ISPRINT(cmd)) {
rb_raise(rb_eArgError, "unknown command '%s%c'", cmd == '\'' || cmd == '\\' ? "\\" : "", cmd);
}
else {
rb_raise(rb_eArgError, "unknown command \"\\x%02X\"", cmd);
}
UNREACHABLE_RETURN(Qundef);
} Использует символ cmd для выполнения различных проверок на file1 (первая таблица ниже) или на file1 и file2 (вторая таблица).
File тесты на одном файле:
Cmd Returns Meaning
"A" | Time | Last access time for file1
"b" | boolean | True if file1 is a block device
"c" | boolean | True if file1 is a character device
"C" | Time | Last change time for file1
"d" | boolean | True if file1 exists and is a directory
"e" | boolean | True if file1 exists
"f" | boolean | True if file1 exists and is a regular file
"g" | boolean | True if file1 has the \CF{setgid} bit
| | set (false under NT)
"G" | boolean | True if file1 exists and has a group
| | ownership equal to the caller's group
"k" | boolean | True if file1 exists and has the sticky bit set
"l" | boolean | True if file1 exists and is a symbolic link
"M" | Time | Last modification time for file1
"o" | boolean | True if file1 exists and is owned by
| | the caller's effective uid
"O" | boolean | True if file1 exists and is owned by
| | the caller's real uid
"p" | boolean | True if file1 exists and is a fifo
"r" | boolean | True if file1 is readable by the effective
| | uid/gid of the caller
"R" | boolean | True if file is readable by the real
| | uid/gid of the caller
"s" | int/nil | If file1 has nonzero size, return the size,
| | otherwise return nil
"S" | boolean | True if file1 exists and is a socket
"u" | boolean | True if file1 has the setuid bit set
"w" | boolean | True if file1 exists and is writable by
| | the effective uid/gid
"W" | boolean | True if file1 exists and is writable by
| | the real uid/gid
"x" | boolean | True if file1 exists and is executable by
| | the effective uid/gid
"X" | boolean | True if file1 exists and is executable by
| | the real uid/gid
"z" | boolean | True if file1 exists and has a zero length Тесты, которые принимают два файла:
"-" | boolean | True if file1 and file2 are identical
"=" | boolean | True if the modification times of file1
| | and file2 are equal
"<" | boolean | True if the modification time of file1
| | is prior to that of file2
">" | boolean | True if the modification time of file1
| | is after that of file2 # File kernel.rb, line 120
def then
unless Primitive.block_given_p
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)'
end
yield(self)
end Передаёт self в блок и возвращает результат блока.
3.next.then {|x| x**x }.to_s #=> "256"
Хорошее использование для then — это передача значений в цепочках методов:
require 'open-uri'
require 'json'
construct_url(arguments).
then {|url| URI(url).read }.
then {|response| JSON.parse(response) }
При вызове без блока метод возвращает Enumerator, что можно использовать, например, для условного прерывания цепочки:
# meets condition, no-op 1.then.detect(&:odd?) # => 1 # does not meet condition, drop value 2.then.detect(&:odd?) # => nil
static VALUE
rb_f_throw(int argc, VALUE *argv, VALUE _)
{
VALUE tag, value;
rb_scan_args(argc, argv, "11", &tag, &value);
rb_throw_obj(tag, value);
UNREACHABLE_RETURN(Qnil);
} Передаёт управление в конец активного блока catch, ожидающего tag. Вызывает UncaughtThrowError, если блока catch для tag нет. Необязательный второй параметр предоставляет возвращаемое значение для блока catch, который в противном случае по умолчанию равен nil. Примеры см. в Kernel::catch.
static VALUE
f_trace_var(int c, const VALUE *a, VALUE _)
{
return rb_f_trace_var(c, a);
} Управляет трассировкой присваиваний глобальным переменным. Параметр symbol идентифицирует переменную (как строковое имя или идентификатор символа). cmd (который может быть строкой или объектом Proc) или блок выполняется каждый раз при присваивании переменной. Блок или объект Proc получает новое значение переменной в качестве параметра. См. также Kernel::untrace_var.
trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
$_ = "hello"
$_ = ' there'
Результат:
$_ is now 'hello' $_ is now ' there'
static VALUE
sig_trap(int argc, VALUE *argv, VALUE _)
{
int sig;
sighandler_t func;
VALUE cmd;
rb_check_arity(argc, 1, 2);
sig = trap_signm(argv[0]);
if (reserved_signal_p(sig)) {
const char *name = signo2signm(sig);
if (name)
rb_raise(rb_eArgError, "can't trap reserved signal: SIG%s", name);
else
rb_raise(rb_eArgError, "can't trap reserved signal: %d", sig);
}
if (argc == 1) {
cmd = rb_block_proc();
func = sighandler;
}
else {
cmd = argv[1];
func = trap_handler(&cmd, sig);
}
if (rb_obj_is_proc(cmd) &&
!rb_ractor_main_p() && !rb_ractor_shareable_p(cmd)) {
cmd = rb_proc_isolate(cmd);
}
return trap(sig, func, cmd);
} Задаёт обработку сигналов. Первый параметр — имя сигнала (строка, например, «SIGALRM», «SIGUSR1» и т. д.) или номер сигнала. Символы «SIG» можно опускать в имени сигнала. Команда или блок задают код, который будет выполнен при возникновении сигнала. Если команда — строка «IGNORE» или «SIG_IGN», сигнал будет игнорироваться. Если команда — «DEFAULT» или «SIG_DFL», будет вызван обработчик Ruby по умолчанию. Если команда — «EXIT», скрипт будет завершён сигналом. Если команда — «SYSTEM_DEFAULT», будет вызван обработчик операционной системы по умолчанию. В противном случае будет выполнена заданная команда или блок. Специальное имя сигнала «EXIT» или номер сигнала ноль будут вызваны непосредственно перед завершением программы. trap возвращает предыдущий обработчик для данного сигнала.
Signal.trap(0, proc { puts "Terminating: #{$$}" })
Signal.trap("CLD") { puts "Child died" }
fork && Process.wait
Результат:
Terminating: 27461 Child died Terminating: 27460
static VALUE
f_untrace_var(int c, const VALUE *a, VALUE _)
{
return rb_f_untrace_var(c, a);
} Удаляет трассировку для указанной команды в данной глобальной переменной и возвращает nil. Если команда не указана, удаляет всю трассировку для этой переменной и возвращает массив, содержащий фактически удалённые команды.
# File warning.rb, line 50 def warn(*msgs, uplevel: nil, category: nil) Primitive.rb_warn_m(msgs, uplevel, category) end
Если предупреждения отключены (например, с помощью флага -W0), ничего не делает. В противном случае преобразует каждое из сообщений в строки, добавляет символ новой строки к строке, если строка не заканчивается на новую строку, и вызывает Warning.warn со строкой.
warn("warning 1", "warning 2")
<em>produces:</em>
warning 1
warning 2 Если указан именованный аргумент uplevel, строка будет дополнена информацией о заданном кадре вызывающего объекта в том же формате, что используется функцией C rb_warn.
# In baz.rb
def foo
warn("invalid call to foo", uplevel: 1)
end
def bar
foo
end
bar
<em>produces:</em>
baz.rb:6: warning: invalid call to foo Если указан именованный аргумент category, передает категорию в Warning.warn. Указанная категория должна быть одной из следующих:
- :deprecated
-
Используется для предупреждения о устаревшем функционале, который может быть удалён в будущем.
- :experimental
-
Используется для экспериментальных функций, которые могут измениться в будущих выпусках.
# File kernel.rb, line 144
def yield_self
unless Primitive.block_given_p
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)'
end
yield(self)
end Передаёт self в блок и возвращает результат блока.
"my string".yield_self {|s| s.upcase } #=> "MY STRING"
Хорошее использование для then — это передача значений в цепочках методов:
require 'open-uri'
require 'json'
construct_url(arguments).
then {|url| URI(url).read }.
then {|response| JSON.parse(response) }
Свойства экземпляра (приватные)
# File ext/json/lib/json/common.rb, line 685
def JSON(object, *args)
if object.respond_to? :to_str
JSON.parse(object.to_str, args.first)
else
JSON.generate(object, args.first)
end
end Если object является строкой, разобрать строку и вернуть результат разбора в виде структуры данных Ruby. В противном случае, сгенерировать JSON текст из объекта структуры данных Ruby и вернуть его.
Аргумент opts передаётся в функцию генерации/разбора. Смотрите документацию для generate и parse.
# File lib/uri/common.rb, line 688
def URI(uri)
if uri.is_a?(URI::Generic)
uri
elsif uri = String.try_convert(uri)
URI.parse(uri)
else
raise ArgumentError,
"bad argument (expected URI object or URI string)"
end
end Возвращает uri, преобразованный в объект URI.
# File lib/rubygems/core_ext/kernel_gem.rb, line 41
def gem(gem_name, *requirements) # :doc:
skip_list = (ENV['GEM_SKIP'] || "").split(/:/)
raise Gem::LoadError, "skipping #{gem_name}" if skip_list.include? gem_name
if gem_name.kind_of? Gem::Dependency
unless Gem::Deprecate.skip
warn "#{Gem.location_of_caller.join ':'}:Warning: Kernel.gem no longer "\
"accepts a Gem::Dependency object, please pass the name "\
"and requirements directly"
end
requirements = gem_name.requirement
gem_name = gem_name.name
end
dep = Gem::Dependency.new(gem_name, *requirements)
loaded = Gem.loaded_specs[gem_name]
return false if loaded && dep.matches_spec?(loaded)
spec = dep.to_spec
if spec
if Gem::LOADED_SPECS_MUTEX.owned?
spec.activate
else
Gem::LOADED_SPECS_MUTEX.synchronize { spec.activate }
end
end
end Используйте Kernel#gem для активации определённой версии gem_name.
requirements — список требований к версии, которому должна соответствовать указанная библиотека, обычно в формате “= example.version.number”. Смотрите Gem::Requirement для того, как указать требования к версии.
Если вы хотите активировать последнюю версию библиотеки, нет необходимости вызывать Kernel#gem, Kernel#require сделает это автоматически.
Kernel#gem возвращает true, если библиотека активирована, иначе false. Если библиотека не найдена, не соответствует требованиям по версии или уже активирована другая версия, будет выброшено исключение.
Kernel#gem следует вызывать перед любыми операторами require (в противном случае RubyGems может загрузить конфликтную версию библиотеки).
Kernel#gem загружает предварительные версии только при указании предварительных requirements:
gem 'rake', '>= 1.1.a', '< 2'
В более старых версиях RubyGems переменная окружения GEM_SKIP могла использоваться для пропуска активации указанных библиотек, например, для тестирования изменений, которые ещё не установлены. Теперь RubyGems использует -I и переменную среды RUBYLIB для пропуска активации библиотеки.
Пример:
GEM_SKIP=libA:libB ruby -I../libA -I../libB ./mycode.rb
# File ext/json/lib/json/common.rb, line 663
def j(*objs)
objs.each do |obj|
puts JSON::generate(obj, :allow_nan => true, :max_nesting => false)
end
nil
end Выводит objs в стандартный вывод (STDOUT) как JSON строки в краткой форме, то есть в одной строке.
# File ext/json/lib/json/common.rb, line 672
def jj(*objs)
objs.each do |obj|
puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false)
end
nil
end Выводит objs в стандартный вывод (STDOUT) как JSON строки в формате с отступами и на нескольких строках.
# File lib/pp.rb, line 624
def pp(*objs)
objs.each {|obj|
PP.pp(obj)
}
objs.size <= 1 ? objs.first : objs
end выводит аргументы в красивом формате.
pp возвращает аргументы.
# File ext/psych/lib/psych/y.rb, line 5 def y *objects puts Psych.dump_stream(*objects) end
Псевдоним для Psych.dump_stream, предназначенный для использования с IRB.
Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.