网安
  • Develop
    • JAVA学习
      • 字节码
      • API开发
      • Web开发
      • 工程结构推荐
      • 创建第一个项目
      • 权限管控
      • 配置文件
      • 日志管理
      • 数据访问
      • 性能监控
      • IoC容器
      • Spring
      • Filter与Listener
      • jsp
      • MVC
      • servlet-1
      • servlet-2
      • servlet-3
      • servlet-4
      • FreeMarker
      • Thymeleaf
      • EL
      • SpEL
      • JSTL
      • 部署
      • JDBC
      • 数据库连接池
      • fastjson
      • jackson
      • XML
      • JSON
      • 序列化
      • Maven
      • 安装与使用
      • 工具
      • 爬虫
    • GO学习
      • GO
        • flag 包
        • goland 远程调试
        • GoReleaser
        • OS 包
        • time 包
        • 格式化输出
    • Lua学习
      • Lua
      • 基础语法
      • LuaJIT
      • 与系统交互
    • Pyhon
      • 基础
      • Django
      • CLI
      • miniforge
      • MockingBird
      • pdb
      • pyc
      • 装的我脑血栓要犯了
      • Python101
      • 反序列化
      • 爬虫
      • Pillow
      • 图像识别
      • flask
    • Speed-Ruby
      • 入门1
      • 入门2 对象
      • 入门3 创建命令
      • Encoding类
      • File类与Dir类
      • IO
      • Proc类
      • Time类与Date类
      • 正则
      • 错误处理与异常
      • 对象、变量和常量
      • 方法
      • 数值
      • 数组
      • 条件判断
      • 循环
      • 运算符
      • Socket编程
      • 字符串
      • 并发与线程
      • 块
      • 类和模块
      • 散列
    • Web
      • HTTP
        • Connection
        • HTTP 报文
        • Vary
      • 笔记
        • 跳转
        • 认证 & 授权
        • 同源策略(SOP)
        • 文件
    • Git 学习笔记
    • JSON
      • JSON 学习笔记
    • HTML
      • Speed-HTML
      • 语法学习
      • HTML字符实体
    • XML
      • XML 学习笔记
    • 计算机基础
      • 操作系统
      • 计算机组成
      • 算法
      • 内存
      • 字符编码
    • gnuplot 学习笔记
    • regex
  • Integrated
    • Linux
      • God-Linux
      • Secure-Linux
      • Power-Linux
      • IO模型
      • Speed-Linux
      • 发行版
      • 工具
      • 启动过程
      • 进程
      • 认证
      • 日志
      • 守护进程
      • 文件
      • 信息
      • VSFTP 配置案例
      • auditd
      • containerd
      • DNS 配置案例
      • Docker
      • Docker-Compose
      • firewalld 实验
      • gpg
      • Iptables
      • httpd
      • LAMP
      • mysql
      • nfs 配置案例
      • openssl
      • PAM
      • samba 配置案例
      • terraform
      • ufw
      • VSFTP 配置案例
    • Network
      • Speed-Net
      • Power-Net
      • SDN 笔记
      • DNS
      • TLS
    • Windows
      • Secure-Win
      • Speed-Win
      • ACL
      • LDAP
      • IPC$(Internet Process Connection)
      • PDB符号文件
      • 工作组
      • WinRM
      • 角色权限
      • 凭据
      • 签名
      • 日志
      • 认证
      • 协议
      • 信息
      • 应用
      • 组策略
      • 域
      • asp站点搭建
      • Exchange 搭建
      • Windows 故障转移集群
      • Windows 基础服务搭建
      • Windows 域搭建
      • 本地抓包
      • PowerShell 笔记
    • 容器
      • Docker
    • 数据库
      • Speed-SQL
      • Power-SQL
      • MSSQL
      • MySQL
      • Postgresql
      • Redis
      • MySQL大小写问题
      • 主键和外键
      • MySQL快速入门
      • 虚拟化
        • ESXi
        • vCenter
  • Plan
    • Mac-Plan
    • Misc-Plan
    • Team-Plan
    • Thinking-Plan
    • VM-Plan
  • Sercurity
    • Power-PenTest
    • BlueTeam
      • 安全建设
      • 分析
      • 加固
      • 取证
      • 应急
      • USB取证
      • 磁盘取证
      • 内存取证
      • ClamAV 部署
      • yara 实验
      • 安防设施搭建使用
      • ZIP明文攻击
      • 流量分析
    • Crypto
      • Crypto
        • 2020 9 G60攻防大赛
        • CTF
        • 2020 9 中能融合杯工控CTF
        • 2020 10 全国工业互联网安全技术技能大赛江苏省选拔赛
        • 2020 10 全国网络与信息安全管理职业技能大赛江苏场
        • 2020 11 I²S峰会暨工业互联网安全大赛
        • 2021 6 第二届I²S峰会暨工业互联网安全大赛
        • 2021-9-第七届工控信息安全攻防竞赛
        • 2021 9 第七届全国职工职业技能大赛某市县选拔赛
        • 2021 9 全国网络与信息安全管理职业技能大赛江苏场
        • 2021-10-G60攻防大赛
    • CTF
      • CTF
      • writeup
        • 2020 9 中能融合杯工控CTF
        • 2020 9 G60攻防大赛
        • 2020 10 全国工业互联网安全技术技能大赛江苏省选拔赛
        • 2020 10 全国网络与信息安全管理职业技能大赛江苏场
        • 2020 11 I²S峰会暨工业互联网安全大赛
        • 2021 6 第二届I²S峰会暨工业互联网安全大赛
        • 2021-9-第七届工控信息安全攻防竞赛
        • 2021 9 第七届全国职工职业技能大赛某市县选拔赛
        • 2021 9 全国网络与信息安全管理职业技能大赛江苏场
        • 2021-10-G60攻防大赛
    • ICS
      • PLC攻击
      • S7comm 相关
      • 工控协议
      • 上位机安全
      • Modbus 仿真环境搭建
      • siemens 仿真搭建实验
      • S7-300 启停实验
    • IOT
      • 无线电安全
        • RFID复制卡
        • RFID基础知识
        • WiFikiller
      • 硬件安全
        • DIY键盘嵌入指纹识别模块实验记录
        • Device-Exploits
        • HID-Digispark
        • HID-KeyboardLogger
        • HID-USBHarpoon
        • HID-USBKeyLogger
      • 固件安全
        • 固件安全
        • Dlink_DWR-932B 路由器固件分析
    • Mobile sec
      • 小程序安全
      • Android安全
    • PWN
      • SLMail溢出案例
      • PWN
    • Red Team
      • OS安全
        • Linux 安全
        • Exploits
        • NTLM中继
        • Windows 安全
        • Responder欺骗
        • Windows-LOL
      • Web_Generic
        • Top 10
          • RCE
          • Fileread
          • SQLi
          • SSRF
          • SSTI
          • Web Generic
          • XSS
          • XXE
      • Web_Tricks
        • JWT 安全
        • HTTP_request_smuggling
        • OOB
        • 绕过访问
      • 靶场
        • Hello-Java-Sec 学习
        • DVWA-WalkThrough
        • pikachu-WalkThrough
        • upload-labs-WalkThrough
        • XVWA-WalkThrough
        • XSS挑战-WalkThrough
      • 实验
        • flask
        • fastjson
        • Log4j
        • nodejs
        • Shiro
        • Spring
        • Weblogic
      • 前端攻防
      • IDOR
    • 安防设备
      • Exploits
      • Bypass 技巧
    • 后渗透
      • 权限提升
      • 后渗透
      • 权限维持
      • 实验
        • C2 实验
        • Exchange
        • 端口转发实验
        • 代理实验
        • 免杀实验
        • 隧道实验
    • 软件服务安全
      • Exploits
      • CS Exploits
      • 实验
        • Docker
        • Kubernetes
        • Mysql
        • Oracle
        • PostgreSQL
        • Redis
        • vCenter
    • 协议安全
      • Exploits
    • 信息收集
      • 端口安全
      • 空间测绘
      • 信息收集
    • 语言安全
      • 语言安全
        • 语言安全
      • GO安全
        • GO安全
        • Go代码审计
      • JAVA安全
        • JAVA安全
        • JAVA代码审计
        • JAVA反序列化
        • SpEL 注入
      • PHP安全
        • PHP安全
        • bypass_disable_function
        • bypass_open_basedir
        • phpinfo
        • PHP代码审计
        • PHP反序列化
        • PHP回调函数
        • 变量覆盖
        • POP
        • 弱类型
        • 伪协议
        • 无字母数字Webshell
      • Python安全
        • pyc反编译
        • Python安全
        • Python 代码审计
        • 沙箱逃逸
      • dotnet安全
      • JS安全
    • 云安全
      • 公有云安全
    • Reverse
      • Reverse
      • FILE
        • ELF
        • BMP
        • JPG
        • PE
        • PNG
        • ZIP
        • 文件头
      • 实验
        • PYAble
          • 2-逆运算
          • 1-基本分析
          • 3-异或
          • 4-Base64
          • 5-Base64换表
          • 6-动态调试
        • Windows
          • condrv.sys 内存损坏漏洞
    • 工具
      • Aircrack
      • BloodHound
      • Burp Suite
      • frp
      • CobaltStrike
      • Ghidra
      • fscan
      • Hashcat
      • IDA
      • merlin
      • Kali
      • Metasploit
      • Mimikatz
      • ModSecurity
      • Nmap
      • nps
      • nuclei
      • pupy
      • RedGuard
      • SET
      • sliver
      • Snort
      • Sqlmap
      • Suricata
      • Sysmon
      • uncover
      • Volatility
      • Wfuzz
      • Wireshark
      • xray
    • 安全资源
      • 靶机
        • VulnHub
          • DC
            • DC2 WalkThrough
            • DC1 WalkThrough
            • DC3 WalkThrough
            • DC4 WalkThrough
            • DC5 WalkThrough
            • DC6 WalkThrough
            • DC9 WalkThrough
            • DC8 WalkThrough
          • It's_October
            • It’s_October1 WalkThrough
          • Kioptrix
            • Kioptrix2 WalkThrough
            • Kioptrix3 WalkThrough
            • Kioptrix4 WalkThrough
            • Kioptrix5 WalkThrough
          • Mission-Pumpkin
            • PumpkinGarden-WalkThrough
            • PumpkinFestival WalkThrough
            • PumpkinRaising WalkThrough
          • Symfonos
            • symfonos1 WalkThrough
            • symfonos2 WalkThrough
            • symfonos3 WalkThrough
            • symfonos5 WalkThrough
        • Wargames
          • Bandit
            • Bandit-WalkThrough
      • 面试问题
        • 面试问题
Powered by GitBook
On this page
  • 创建命令
  • 命令行的输入数据
  • 文件的读取
  • 方法的定义
  • 其他文件的引用
  • pp 方法
  1. Develop
  2. Speed-Ruby

入门3 创建命令

创建命令


  • https://www.kancloud.cn/imxieke/ruby-base/107289


来实际体验一下如何用 Ruby 实现 Unix 的 grep 命令,以便大家了解用 Ruby 编写程序的大概流程。

命令行的输入数据

到目前为止,我们写的程序都是向屏幕输出数据。现在我们考虑一下怎么输入数据。在创建命令前,我们首先得知道怎么使用命令。那么,让我们先来看看怎么把数据传递给程序。

向程序传递数据,最简单的方法就是使用命令行。Ruby 程序中,使用 ARGV 这个 Ruby 预定义好的数组来获取从命令行传递过来的数据。数组 ARGV 中的元素,就是在命令行中指定的脚本 字符串参数。

在命令行指定多个脚本参数时,各参数之间用空格间隔。

puts "首个参数: #{ARGV[0]}"
puts "第2 个参数: #{ARGV[1]}"
puts "第3 个参数: #{ARGV[2]}"
> ruby print_argv.rb 1st 2nd 3rd
首个参数: 1st
第 2 个参数: 2nd
第 3 个参数: 3rd

使用数组 ARGV 后,程序需要用到的数据就不必都写在代码中。同时,抽取数据、保存数据等普通的数组操作对于 ARGV 都是适用的。

name = ARGV[0]
print "Happy Birthday, ", name, "!\n"

执行示例

> ruby happy_birth.rb Ruby
Happy Birthday, Ruby!

从参数里得到的数据都是字符串,因此如果希望进行运算时,需要对获得的数据进行类型转换。把字符串转换为整数,我们可以使用 to_i 方法。

num0 = ARGV[0].to_i
num1 = ARGV[1].to_i
puts "#{num0} + #{num1} = #{num0 + num1}"
puts "#{num0} - #{num1} = #{num0 - num1}"
puts "#{num0} * #{num1} = #{num0 * num1}"
puts "#{num0} / #{num1} = #{num0 / num1}"

执行示例

> ruby arg_arith.rb 5 3
5 + 3 = 8
5 - 3 = 2
5 * 3 = 15
5 / 3 = 1

文件的读取

Ruby 脚本除了读取命令行传递过来的字符串参数外,还可以读取预先写在文件里的数据。

Ruby 的源代码中,有一个名为 ChangeLog 的文本文件。文件里面记录了 Ruby 相关的修改日志。

文件内容如下所示:

                                        ┊
Mon Feb 27 23:46:09 2012  Yukihiro Matsumoto  <matz@ruby-lang.org>

     * parse.y (opt_bv_decl): allow newline at the end.  [ruby-dev:45292]
                                        ┊

从文件中读取内容并输出

首先,我们先做一个简单文件内容读取程序。读取文件内容的流程,如下所示:

  1. 打开文件。

  2. 读取文件的文本数据。

  3. 输出文件的文本数据。

  4. 关闭文件。

filename = ARGV[0]
file = File.open(filename)  # ①
text = file.read            # ②
print text                  # ③
file.close                  # ④

与之前的例子相比,这个例子的代码终于有点程序的模样了,接下来我们逐行分析。

第 1 行,将命令行参数 ARGV[0] 赋值给变量 filename。也就是说,filename 表示我们希望读取的文件名。 第 2 行,File.open(filename) 表示打开名为 filename 的文件,并返回读取该文件所需的对象。可能会有读者不太明白什么是“读取该文件所需的对象”,不过不要紧,目前我们暂时只需要知道有这么一个对象就可以了。

“读取该文件所需的对象”实际在第 3 行使用。在这里,read 方法读取文本数据,并将读取到的数据赋值给 text 变量。接下来,第 4 行的代码会输出 text 的文本数据。到目前为止,我们使用过好多次 print 方法了,大家应该不会陌生了吧。然后,程序执行最后一段代码的 close 方法。这样,就可以关闭之前打开了的文件了。

像下面那样执行这个程序后,指定的文件内容会一下子全部输出到屏幕中。

ruby read_text.rb 文件名

其实,如果只是读取文件内容,直接使用 read 方法会使程序更简单。

filename = ARGV[0]
text = File.read(filename)
print text

更进一步,如果不使用变量,一行代码就可以搞定了。

print File.read(ARGV[0])

从文件中逐行读取内容并输出

现在,我们了解了如何使用 Ruby 读取并输出文件里的所有内容。但是,刚才的程序有如下的问题:

  • 一下子读取全部文件内容会很耗时;

  • 读取文件的内容会暂时保存在内存中,遇到大文件时,程序有可能因此而崩溃。

例如一个文件有 100 万行数据,我们只希望读取其最初的几行。这种情况下,如果程序不管三七二十一读取文件的全部内容,无论从时间还是内存角度来讲,都是严重的浪费。

因此,我们只能放弃“读取文件全部内容”的做法,将程序改为逐行读取并输出。这样,只需要具备当前行数据大小的内存就足够了。

filename = ARGV[0]
file = File.open(filename)
file.each_line do |line|
  print line
end
file.close

程序的第 1 行和第 2 行和前面的一样的,从第 3 行开始有了变化。程序的第 3 行到第 5 行使用了 each_line 方法。

each_line 方法很像 each 方法。each 方法是用于逐个处理数组元素,顾名思义,each_line 方法就是对文件进行逐行处理。因此在这里,程序会逐行读取文件的内容,使用 print 方法输出该行的文件内容 line,直到所有行的内容输出完为止。

从文件中读取指定模式的内容并输出

Unix 中有一个叫 grep 的命令。grep 命令利用正则表达式搜索文本数据,输出按照指定模式匹配到的行。我们试试用 Ruby 实现 grep 命令。

pattern = Regexp.new(ARGV[0])
filename = ARGV[1]

file = File.open(filename)
file.each_line do |line|
  if pattern =~ line
    print line
  end
end
file.close

命令行输入以下命令

ruby simple_grep.rb 模式 文件名

程序有点长,我们逐行分析一下。

Ruby 执行该脚本时,需要有两个命令行参数——ARGV[0] 和 ARGV[1]。第 1 行,程序根据第 1 个参数创建了正则表达式对象,并赋值给变量 pattern。Regexp.new(str) 表示把字符串 str 转换为正则表达式对象。接着第 2 行,把第 2 个参数赋值给作为文件名的变量 filename

第 4 行,打开文件,创建文件对象,并将其赋值给变量 file。

第 5 行,读取一行数据,并将其赋值给变量 line。

第 6 行,使用 if 语句,判断变量 line 的字符串是否匹配变量 pattern 的正则表达式。如果匹配,则在程序第 7 行输出该字符串。这个 if 语句没有 else 部分,因此,若不匹配程序什么都不会做。程序循环读取文件,重复以上操作。

假设我们希望输出 Changelog 文件中含有 matz 的行,可以执行以下命令:

ruby simple_grep.rb matz Changelog

matz 是松本行弘先生的昵称,这样我们就可以轻松找到他的修改之处了。

方法的定义

到目前为止,我们用过很多 Ruby 的方法了,其实我们也能定义方法。定义方法的语法如下所示:

def 方法名
 希望执行的处理
end

假设我们需要定义一个输出“Hello, Ruby.”的方法。

def hello
  print "Hello, Ruby.\n"
end

执行这 3 行代码的程序,实际并不会输出任何结果。这是由于在调用 hello 方法前,程序就已经结束了。因此方法定义好后,我们还要通过“调用”告诉 Ruby,我们要执行这个方法。

def hello
  puts "Hello, Ruby"
end

hello()

执行示例

> ruby hello_ruby2.rb
Hello, Ruby

执行 hello() 调用了 hello 方法后,程序就会执行第 1 ~ 3 行定义的内容。

其他文件的引用

有时,我们希望在其他的程序里也能重复使用程序的某部分。例如,在某个程序里写好某个方法,在其他程序里也可以调用。

大部分的编程语言都提供了把多个不同程序组合为一个程序的功能。像这样,被其他程序引用的程序,我们称为库(library)。

Ruby 使用 require 方法来引用库。

require 希望使用的库名

库名可以省略后缀 .rb。

调用 require 方法后,Ruby 会搜索参数指定的库,并读取库的所有内容。库内容读取完毕后,程序才会执行 require 方法后面的处理。

我们来实际操作一下,将刚才已经完成的 simple_grep.rb 作为库提供给其他程序引用。作为库的文件不用做特别的修改,我们只需把定义了 simple_grep 方法的文件,和引用该文件的程序文件放在同一个文件夹即可。

def simple_grep(pattern, filename)
  file = File.open(filename)
  file.each_line do |line|
    if pattern =~ line
      print line
    end
  end
  file.close
end
require "./grep"                # 读取 grep.rb(省略“.rb”)

pattern = Regexp.new(ARGV[0])
filename = ARGV[1]
simple_grep(pattern, filename)  # 调用 simple_grep 方法

这里,程序把执行 simple_grep 方法时所需要的检索模式以及文件名两个参数,分别赋值给 pattern 变量以及 filename 变量。请注意,在这个例子里,use_grep.rb 引用了在 grep.rb 定义的 simple_grep 方法。执行以下命令输出 Changelog 文件里包含 matz 字符串的行。

> ruby use_grep.rb matz Changelog

库与脚本放在同一文件夹时,需要用 ./ 来明示文件存放在当前目录。

Ruby 提供了很多便利的标准库,在我们的程序需要用到时,都可以使用 require 方法加以引用。

例如,我们的程序可以引用 date 库,这样程序就可以使用返回当前日期的 Date.today 的方法,或者返回指定日期对象的 Date.new 方法。下面是一个求从 Ruby 的生日—— 1993 年 2 月 24 日到今天为止的天数的小程序。

require "date"

days = Date.today - Date.new(1993, 2, 24)
puts(days.to_i)    #=> 7396

pp 方法

Ruby 除了提供 p 方法外,还提供了一个有类似作用的方法——pp。pp 是英语 pretty print 的缩写。使用 pp方法,我们需要使用 require 方法引用 pp 库。

require "pp"
 
v = [{
     key00: "《Ruby 基础教程 第4 版》",
     key01: "《Ruby 秘笈》",
     key02: "《Rails3 秘笈》"
   }]
p v
pp v
> ruby p_and_pp.rb
[{:key00=>"《Ruby 基础教程 第4 版》", :key01=>"《Ruby 秘笈》", :key02=>"《Rails3 秘笈》"}]
[{:key00=>"《Ruby 基础教程 第4 版》",
 :key01=>"《Ruby 秘笈》",
 :key02=>"《Rails3 秘笈》"}]

与 p 方法有点不同,pp 方法在输出对象的结果时,为了更容易看懂,会适当地换行以调整输出结果。建议在需要确认嵌套的内容时使用 pp 方法。

Previous入门2 对象NextEncoding类