%Q, %q, %W, %w, %x, %s, %i
%Q
# %Q 用于代替双引号字符串,当你需要在字符串里放入很多引号时候, 可以直接用下面方法而不需要在引号前逐个添加反斜杠 (\")
# (...)也可用其他非数字字母的符号或成对的符号代替, 诸如[...], !...!, +...+,{...}, <...>等.
what_frank_said = "hello!"
puts %Q(Joe said: "Frank said: "#{what_frank_said}"")
#输出结果:
Joe said: "Frank said: "hello!""
%q
# 与`%Q`类似, 但是表示的是单引号字符串
what_frank_said = 'hello!'
puts %q(Joe said: 'Frank said: '#{what_frank_said}' ')
#输出结果:
Joe said: 'Frank said: '#{what_frank_said}' '
%W
# 与`%Q`类似, 但是表示的是单引号字符串
require 'pp'
foo = 'foo'
pp %W(#{foo} Bar Bar\ with\ space)
#输出结果:
["foo", "Bar", "Bar with space"]
%w
# 用于表示其中元素被单引号括起的数组
require 'pp'
pp %w(eat Bar c d)
#输出结果:
["eat", "Bar", "c", "d"]
%x
# 使用`方法执行一段shell脚本并返回标准输出内容.
require 'pp'
foo = 'foo'
pp %x(echo foo:#{foo})
#输出结果:
"foo:foo\n"
%s
#用于表示symbol, 但是不会对其中表达式等内容进行转化
require 'pp'
pp %s(foo)
#输出结果:
:foo
%i
# Ruby 2.0 之后引入的语法, 用于生成一个symbol数组
require 'pp'
pp %i[a b c d e]
#输出结果:
[:a, :b, :c, :d, :e]
调用外部可执行文件
exec
#exec('echo hello,`whoami`')
#exec后面 不会被执行 system会执行
#puts '*' * 30
#输出结果:
hello,yutangzhao
system
#返回值true表示成功 false表示失败
pp system('echo hello,`whoami`')
#system后面 不会被执行
puts '*' * 30
pp system('ls xxxx')
#输出结果:
hello,yutangzhao
true
******************************
ls: xxxx: No such file or directory
false
if system('echo hello,`whoami`')
puts 'success'
else
put 'faild'
end
#输出结果:
hello,yutangzhao
success
system('echo hello,`whoami`')
pp $?
pp system('ls xxxx')
pp $?
pp $?.exitstatus
if $?.exitstatus.zero?
puts 'ok'
else
puts 'faild'
end
##输出结果:
hello,yutangzhao
#<Process::Status: pid 8013 exit 0>
ls: xxxx: No such file or directory
false
#<Process::Status: pid 8016 exit 1>
1
faild
system 高级用法
#方法原形
system([env,],command,[,options])
#configure脚本文件
#!/usr/bin/env ruby
require 'pp'
system('rm -rf out err')
stout = File.open('out','w+')
sterr = File.open('err','w+')
$stdout.reopen(stout)
$stderr.reopen(sterr)
pp "ENV['NAME']: #{ENV['NAME']}"
pp "ENV['AGE']: #{ENV['AGE']}"
puts "ARGV:"
pp ARGV
#注意给configure脚本文件添加可执行权限
chmod a+x configure
#main.rb通过system执行configure脚本
name = 'hanghang'
age = '34'
favors = %W[aaa bb ccc dd]
pp system(
{ 'NAME' => 'zhangsan','AGE' => '34'},
'./configure',
name, age, *favors
)
p $?
#运行结果:
true
#<Process::Status: pid 10195 exit 0>
#查看out文件
"ENV['NAME']: zhangsan"
"ENV['AGE']: 34"
ARGV:
["hanghang", "34", "aaa", "bb", "ccc", "dd"]
require_relative
run.rb
def run
puts 'run.rb ----'
end
require 'pp'
require_relative 'run' #相对于当前文件的路径
#require_relative 'yang/run'
#require_relative '../run'
run
#输出结果:
run.rb ----
LOAD_PATH
require 'pp'
#require '/Users/yutangzhao/Desktop/run.rb' #默认做法
$LOAD_PATH.unshift('/Users/yutangzhao/Desktop') #路径添加到load_path中
require 'run'
run
pp '*' * 50
pp $LOAD_PATH
#输出结果:
run.rb ----
"**************************************************"
["/Users/yutangzhao/Desktop",
"/Users/yutangzhao/.rvm/rubies/ruby-2.7.2/lib/ruby/site_ruby/2.7.0",
"/Users/yutangzhao/.rvm/rubies/ruby-2.7.2/lib/ruby/site_ruby/2.7.0/x86_64-darwin20",
"/Users/yutangzhao/.rvm/rubies/ruby-2.7.2/lib/ruby/site_ruby",
"/Users/yutangzhao/.rvm/rubies/ruby-2.7.2/lib/ruby/vendor_ruby/2.7.0",
"/Users/yutangzhao/.rvm/rubies/ruby-2.7.2/lib/ruby/vendor_ruby/2.7.0/x86_64-darwin20",
"/Users/yutangzhao/.rvm/rubies/ruby-2.7.2/lib/ruby/vendor_ruby",
"/Users/yutangzhao/.rvm/rubies/ruby-2.7.2/lib/ruby/2.7.0",
"/Users/yutangzhao/.rvm/rubies/ruby-2.7.2/lib/ruby/2.7.0/x86_64-darwin20"]
require 'pp'
#require '/Users/yutangzhao/Movies/Ruby/tool.rb' #默认做法
#require File.expand_path('../tool.rb',__FILE__) #cocoapods做法
load(File.expand_path('../tool.rb',__FILE__))
run
pp '*' * 25 + '打印路径' + '*' * 25
pp File.expand_path('../tool.rb',__FILE__)
#输出结果:
tool.rb ----
"*************************打印路径*************************"
"/Users/yutangzhao/Movies/Ruby/tool.rb"
autoload
#Tool.rb
module Tool
def run
puts 'module--tool.rb ----'
end
end
===================================
require 'pp'
#autoalod(名字空间:Tool,tool.rb 绝对路径)
autoload(:Tool, File.expand_path('../tool.rb',__FILE__))
include(Tool)
run
self.send(:run)
#输出结果:
module--tool.rb ----
module--tool.rb ----
加载文件方式的区别
#多次require_relative 代码只会初始化一次
require_relative 'tool'
require File.expand_path('../tool',__FILE__)
#需要使用完整的路径名,load 调用一次代码就会执行一次
load File.expand_path('../tool.rb',__FILE__)
#用到的时候才会执行,相当于oc initialize
autoload(:Tool, File.expand_path('../tool.rb',__FILE__))
module
require 'pp'
module AAA
NAME = 'hanghang'
AGE = 99
def run
puts 'aaa run....'
end
def self.sleep
puts 'aaa sleep...'
end
#让module中的对象方法,也可以通过module::method方式调用 ,不建议这样做 会破坏module的封装性
module_function:run
class Dog
end
class Cat
end
module AAASub
NAME = 'lisi'
AGE = 88
end
end
puts AAA::NAME
puts AAA::AGE
# AAA::run #=> error 只能通过include/extend/prepend 扩展才能使用
AAA::sleep
pp AAA::Dog.new
pp AAA::Cat.new
pp AAA::AAASub::NAME
pp AAA::AAASub::AGE
#输出结果:
hanghang
99
aaa sleep...
#<AAA::Dog:0x00007f90f1132228>
#<AAA::Cat:0x00007f90f11309a0>
"lisi"
88
====================main.rb====================
require_relative 'module'
AAA::run
#输出结果:
aaa run....
module扩展方式
- include 影响方法查找链顺序
require_relative 'module'
#打印方法查找链
pp self.class.ancestors
include(AAA)
pp self.class.ancestors
eat
#类方法不需要扩展
AAA.sleep
#输出结果:
[Object, PP::ObjectMixin, Kernel, BasicObject]
[Object, AAA, PP::ObjectMixin, Kernel, BasicObject]
aaa eat....
aaa sleep....
- extend 不影响方法查找链顺序
require_relative 'module'
#打印方法查找链
pp self.class.ancestors
extend(AAA)
eat
pp self.class.ancestors
#输出结果:
[Object, PP::ObjectMixin, Kernel, BasicObject]
aaa eat....
[Object, PP::ObjectMixin, Kernel, BasicObject]
============对象exend(module方法)================
require_relative 'module'
class Person
end
obj = Person.new
#打印方法查找链
pp obj.class.ancestors
obj.extend(AAA)
obj.eat
pp obj.class.ancestors
#输出结果:
[Person, Object, PP::ObjectMixin, Kernel, BasicObject]
aaa eat....
[Person, Object, PP::ObjectMixin, Kernel, BasicObject]
============类exend(module方法)================
require_relative 'module'
class Person
end
#打印方法查找链
pp Person.ancestors
Person.extend(AAA)
Person.eat
pp Person.ancestors
#输出结果:
[Person, Object, PP::ObjectMixin, Kernel, BasicObject]
aaa eat....
[Person, Object, PP::ObjectMixin, Kernel, BasicObject]
- prepend 只能在类的作用域里扩展
require_relative 'module'
class Person
end
pp Person.ancestors
class Person
prepend(AAA)
end
Person.new.eat
pp Person.ancestors
#输出结果:
[Person, Object, PP::ObjectMixin, Kernel, BasicObject]
aaa eat....
[AAA, Person, Object, PP::ObjectMixin, Kernel, BasicObject]
注意点: 只有对象方法才可以扩展给外界使用,类方法不需要扩展可以直接使用;ruby本身不支持多继承,可以通过扩展实现多继承的效果
class 与module的关系
class也是module的一种
class Config
def hello(name)
puts "hello #{name}"
end
module Mixin
def xxx_hello(val)
Config.new.hello(val)
end
end
end
class Icon
include(Config::Mixin)
end
#单列扩展使用,调用会更简洁
Icon.new.xxx_hello('kitty')
#输出结果:
hello kitty
method_missing
class Person
def self.run
puts '*' * 50
end
def eat
puts '?' * 50
end
def self.method_missing(method, *args, &block)
puts "你调用了一个不存在的类方法 #{method}"
end
def method_missing(method, *args, &block)
puts "你调用了一个不存在的对象方法 #{method}"
end
end
Person.haha #类方法
Person.new.sleep #对象方法
#输出结果:
你调用了一个不存在的类方法 haha
你调用了一个不存在的对象方法 sleep
gitlab module定义方式
module Gitlab
class Client
def self.run
puts 'run.......'
end
end
end
# 调用类
Gitlab::Client.run
#打开类
module Gitlab
class Client
def self.sleep
puts 'sleep.......'
end
end
end
#gitlab 打开类写法
class Gitlab:: Client
def self.eat
puts 'eat.....'
end
end
Gitlab::Client.run
Gitlab::Client.sleep
Gitlab::Client.eat
puts '=' * 50
module AAA
module BBB
module CCC
module DDD
class Person
def self.jump
puts 'jump...'
end
end
end
end
end
end
#module多层嵌套打开方式
class AAA::BBB::CCC::DDD::Person
def self.fly
puts 'fly.....'
end
end
AAA::BBB::CCC::DDD::Person.fly
#输出结果:
run.......
run.......
sleep.......
eat.....
==================================================
fly.....
module的accestor
module Configuration
#%i 用于生成一个symbol数组
VALID_OPTIONS_KEYS = %i[endpoint private_token user_agent sudo httpparty].freeze
attr_accessor(*VALID_OPTIONS_KEYS)
end
module Gitlab
extend Configuration
end
Gitlab.endpoint = 'https://www.baidu.com'
Gitlab.private_token = 'DEDSdddadd'
puts "endpoint: #{Gitlab.endpoint}"
puts "private_token:#{Gitlab.private_token}"
open class
require 'pp'
class String
def haha
puts 'haha'
end
end
"123".haha
#输出结果:
haha
open instance
require 'pp'
class Person
def run
puts 'run.....'
end
end
obj = Person.new
def obj.run
puts 'hook....'
super
end
obj.run
puts '='*25 + '原始方法实现' + '='*25
Person.new.run
#输出结果:
yutangzhao@yutangzhaodeMacBook-Pro Ruby % ruby main.rb
hook....
run.....
=========================原始方法实现=========================
run.....
prepend hook
================Animal.rb=====================
class Animal
def cry
puts 'cry.....'
end
end
================main.rb=====================
require 'pp'
require_relative 'animal'
module AnimalPatch
def cry
puts 'hook....'
#调用原始方法
super
end
end
#打开类
class Animal
prepend(AnimalPatch)
end
Animal.new.cry
#输出结果:
hook....
cry.....
instance_method hook
================Animal.rb=====================
module Animal
class Dog
def run
puts 'run.....'
end
end
end
================main.rb=====================
require 'pp'
require_relative 'animal'
#打开类
module Animal
class Dog
origin_run_method = instance_method(:run)
define_method(:run) do
puts 'hook....'
#调用原来的方法
origin_run_method.bind(self).call
end
end
end
Animal::Dog.new.run
#输出结果:
hook....
run.....
DSL
#执行一端ruby代码字符串
eval("def run ; puts 'run ...';end") #=>ruby main.rb
eval("run")
#输出结果:
run ...
spec
================podspec.rb=====================
class Spec
attr_accessor :name, :version, :license, :summary
def initialize
@name = 'tangge'
@version = '1.2.1'
@license = 'APCH MTI'
@summary = 'this is a beautiful vendor'
yield self if block_given?()
end
end
================ruby.podspec=====================
Spec.new do |s|
s.name = 'AFNetworking'
s.version = '4.1.2'
s.license = 'MIT'
s.summary = 'A delightful newworking library for Apple platform'
end
================main.rb=====================
#1.导入podspec实体类
require_relative 'podspec'
#2.读取ruby.podspec
str = File.read('ruby.podspec')
#3.解释创建Pod::spec对象
spec = eval(str)
#4.拿到spec对象的各种DSL属性值
puts spec.name
puts spec.version
puts spec.license
puts spec.summary
#输出结果:
AFNetworking
4.1.2
MIT
A delightful newworking library for Apple platform