我是Ruby编程的新手,现在我正在使用Rbox / Rye编写一些测试自动化ruby脚本。
作为测试的一部分,客户将一个+ 10GB的文件上传到ftp主机
该脚本每分钟检查文件是否仍在上传,上传完成或上传失败
对于测试,我使用Rbox / Rye execute shell命令查找文件统计信息:
def check_file_upload()
rbox = Rye::Box.new("#{@host}")
rbox.disable_safe_mode
result = rbox.execute "stat #{@file}"
end
stats = file.check_file_upload()
puts stats
" put"正确打印文件统计信息。格式与我执行" stat文件相同的格式" linux主机上的命令。
现在,有没有办法可以实际解析由
返回的值
check_file_upload()
方法。我可以使用Ruby内置的正则表达式,或者grep / awk,从返回的文件统计信息中选择特定信息。
以下是文件统计信息:
File: `/home/user/file_name.dmp'
Size: 11594768384 Blocks: 22668184 IO Block: 4096 regular file
Device: 802h/2050d Inode: 57442314 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1504/user) Gid: ( 1504/user)
Access: 2015-01-06 11:32:17.000000000 -0700
Modify: 2015-01-06 11:38:59.000000000 -0700
Change: 2015-01-06 11:38:59.000000000 -0700
更具体地说,我想挑选文件大小,访问,修改和更改值
答案 0 :(得分:0)
是的,这对正则表达式来说是一个简单的任务。这是一个解析来自" stat"的有趣位的类。 string并将它们公开为属性:
class FileStatInfo
attr_reader :size, :access, :modify, :change
def initialize(string)
string.split(/\n/).each do |line|
if line =~ /^Size:\s*(\d+)/
@size = $1.to_i
elsif line =~ /^Access:\s*(.*)/
@access = $1.strip # Or Date.parse($1.strip)
# ...
end
end
end
end
# ...
stat_info = FileStatInfo.new(file.check_file_upload)
stat_info.size # => 11594768384
stat_info.access # => "2015-01-06 11:32:17.000000000 -0700"
答案 1 :(得分:0)
使用str
提取字符串check_file_upload()
后,可以构建一个哈希来保存感兴趣的值。
<强>代码强>
def extract(str, keepers)
r = /\w+:\s(?:\S+\s)*\S+/
str.lines.each_with_object({}) do |line, h|
line.scan(r).each do |s|
k,_,v = s.partition(/:\s+/)
v = v.to_i if v =~ /^\d+$/
h.update({ k=>[v] }) { |_,ov,nv| ov+nv } if keepers.include?(k)
end
end
end
示例强>
我理解以下是check_file_upload()
生成的典型字符串:
str =
"Size: 11594768384 Blocks: 22668184 IO Block: 4096 regular file
Device: 802h/2050d Inode: 57442314 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1504/user) Gid: ( 1504/user)
Access: 2015-01-06 11:32:17.000000000 -0700
Modify: 2015-01-06 11:38:59.000000000 -0700
Change: 2015-01-06 11:38:59.000000000 -0700"
数组keepers
标识要从此字符串中提取的数据:
keepers = %w{ Size Access Modify Change }
#=> ["Size", "Access", "Modify", "Change"]
extract(str, keepers)
#=> {"Size"=>[11594768384],
# "Access"=>["(0644/-rw-r--r--)", "2015-01-06 11:32:17.000000000 -0700"],
# "Modify"=>["2015-01-06 11:38:59.000000000 -0700"],
# "Change"=>["2015-01-06 11:38:59.000000000 -0700"]}
<强>解释强>
我们的正则表达式是:
r = /\w+:\s(?:\S+\s)*\S+/
对于上面的示例:
str.lines
#=> ["Size: 11594768384 Blocks: 22668184 IO Block: 4096 regular file \n",
# "Device: 802h/2050d Inode: 57442314 Links: 1\n",
# "Access: (0644/-rw-r--r--) Uid: ( 1504/user) Gid: ( 1504/user) \n",
# "Access: 2015-01-06 11:32:17.000000000 -0700 \n",
# "Modify: 2015-01-06 11:38:59.000000000 -0700 \n",
# "Change: 2015-01-06 11:38:59.000000000 -0700"]
Enumerable#each_with_object创建一个由块变量h
表示的初始空哈希,并将数组str.lines
的每个元素传递到块中,并将其分配给块变量{{1 }}。最初,
line
在我们计算的块中:
line = "Size: 11594768384 Blocks: 22668184 IO Block: 4096 regular file \n"
h = {}
请注意,a = line.scan(r)
#=> ["Size: 11594768384", "Blocks: 22668184", "Block: 4096"]
被错误地提取,但不管那个字段是不是必需的。
"IO Block: 4096 regular file"
这里,第一个字符串a.each do |s|
k,_,v = s.partition(/:\s+/)
v = v.to_i if v =~ /^\d+$/
h.update({ k=>[v] }) { |_,ov,nv| ov+nv } if keepers.include?(k)
end
h #=> {"Size"=>[11594768384]}
传入其块
each
所以
s = "Size: 11594768384"
我们使用Hash#update(a.k.a。k,_,v = s.partition(/:\s+/)
#=> ["Size", ": ", "11594768384"]
v =~ /^\d+$/ #=> 0
v = v.to_i if v =~ /^\d+$/
#=> 11594768384
h.update({ k=>[v] }) { |_,ov,nv| ov+nv } if keepers.include?(k)
#=> {}.update({ "Size"=>[11594768384] }) if
# ["Size", "Access", "Modify", "Change"].include?("Size")
#=> true
h #=> { "Size=>[11594768384] }
)的形式,它使用块来解析合并的两个哈希中包含的键的值。
由于merge!
既不包含keepers
也不包含"Blocks"
,因此这些键的哈希值不会合并到"Block"
中。
对于h
的下一个元素:
str.lines
在line = "Device: 802h/2050d Inode: 57442314 Links: 1\n"
中不包含任何键,因此哈希keepers
中没有添加任何内容。以下一行:
h
将line = "Access: (0644/-rw-r--r--) Uid: ( 1504/user) Gid: ( 1504/user) \n"
添加到哈希值,因此我们得到:
{ "Access"=>["(0644/-rw-r--r--)"] }
接下来,
h = { "Size"=>[11594768384], "Access"=>["(0644/-rw-r--r--)"] }
所以
line = "Access: 2015-01-06 11:32:17.000000000 -0700 \n"
从这个数组传入其块的唯一元素是{<1}}:
a = line.scan(r)
#=> ["Access: 2015-01-06 11:32:17.000000000 -0700"]
由于each
已包含密钥s = "Access: 2015-01-06 11:32:17.000000000 -0700"
k,_,v = s.partition(/:\s+/)
#=> ["Access", ": ", "2015-01-06 11:32:17.000000000 -0700"]
v =~ /^\d+$/
#=> nil
v = v.to_i if v =~ /^\d+$/ # no conversion to integer
h.update({ k=>[v] }) { |_,ov,nv| ov+nv } if keepers.include?(k)
#=> {"Size"=>[11594768384],
# "Access"=>["(0644/-rw-r--r--)", "2015-01-06 11:32:17.000000000 -0700"]}
,因此调用h
的块以确定执行合并后k => Access"
的值。三个块变量是:
update
"Access"
的值是数组k = "Access" # not used, so replaced with an underscore
ov = ["(0644/-rw-r--r--)" # "old" value
nv = ["2015-01-06 11:32:17.000000000 -0700"] # "new" value
和"Access"
的总和,如上所示。
ov
的其余元素的处理方式类似。