我正在寻找解析和更新文档的解决方案。一个很好的例子是user.js脚本。
示例案例:
用户将user.js
脚本上传到userscripts.org。文件必须具有浏览器特定变量的头部。 e.g:
// ==UserScript==
// @name Fancy Title
// @description Fancey Description
// @namespace http://example.com
// @icon http://example.com/icon.png
// @updateURL http://example.com/user.js
// @downloadURL http://example.com/user.js
// @homepageURL http://example.com
// @require https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// @include http*://example.com
// @include http://example.com/scripts/*
// @include http://example.com/tags/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_listValues
// @version 1.0
// ==/UserScript==
将这些变量以及modify
或add
重新检查到文档中会有什么好方法。基本上从@testing.title
=>导入变量@name Fancy Title
,反之亦然。
假设Meta Head
不包含变量@udpateURL
和@downloadeURL
,我会分别添加它们。
我的第一个猜测是regex
使用(@\w+)
扫描文档,这将获取所有变量@
,但从那里我迷失了:)
我可以用纯红宝石解决这个问题,还是有方便的宝石?
修改
Sam 指出:\/\/\s*@(\w+)\s+(.*)
它完全捕获了我需要的变量..
标识符(@title
)和值(Fancy Title
)。
我如何设置,阅读或更新它们?
@MrYoshiji为我提供了一个非常棒的正则表达式Meta Reader:
raw_metas = file_content.scan( /\A\/\/\s==UserScript==(\w|\W)*\/\/\s==\/UserScript==/ )
metas = {}
raw_metas.split(/\r\n|\n|\r/).each do |line_with_meta|
attribute_name = line_with_data.scan(/@\w+/)
value = line_with_data.sub("// #{attribute_name}", '').strip
if metas[attribute_name.sub('@', '').to_sym].present?
metas[attribute_name.sub('@', '').to_sym] = [ metas[attribute_name.sub('@', '').to_sym], value].flatten
else
metas[attribute_name.sub('@', '').to_sym] = value
end
end
但我完全迷失了如何将其设置为与我的模型属性进行交互。
我需要更改哪些元数据
这意味着这些属性(:description等)存储在我的模型中,我需要传递它们。
// @name => @model.name
// @description => @model.description
// @namespace => Application root_path
// @updateURL => @model show_view url
// @downloadURL => @Model show_view url
// @homepageURL => Application root_path
// @include => Custom url (passed by me)
// @include => Custom url (passed by me)
// @include => Custom url (passed by me)
// @version => @model.version
答案 0 :(得分:1)
[编辑:在聊天中,您提到您的输入可能在一行上。这个second demo显示了一个处理它的正则表达式,以及重建字符串的一般过程。]
此代码将名称和值存储在两个哈希中,用@version
替换2.0
,然后输出它们(请参阅online demo底部的输出):
subject = <<-eos
@name Fancy Title
// @description Fancey Description
// @namespace http://example.com
// @icon http://example.com/icon.png
// @updateURL http://example.com/user.js
// @downloadURL http://example.com/user.js
// @homepageURL http://example.com
// @require https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// @include http*://example.com
// @include http://example.com/scripts/*
// @include http://example.com/tags/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_listValues
// @version 1.0
eos
regex = /\/\/ (@\w+)\s*([^\n]*)/
# put captures in two hashes
tokens = Hash.new
values = Hash.new
counter = 0
subject.scan(regex) {|m|
tokens[counter] = $1
values[counter] = $2
counter += 1
}
# find hash key for @version
versionkey = tokens.index("@version")
# change version to 2.0
values[versionkey] = "2.0"
# print names and values
i=0
while i < counter do
puts "#{tokens[i]} : #{values[i]}"
i +=1
end
关键是令牌名称被捕获到组1,并且令牌值被捕获到组2(参见下面的正则表达式解释)。我们用这两组中的值构建哈希值。
要操纵值,您有以下几种选择:
使用正则表达式gsub
替换字符串中的行(不推荐)
直接操作散列中的值到您心中的内容,如演示中所示,其中@version
更改为2.0
,然后根据需要重建字符串。这就是我要做的。
解释正则表达式
// # '// '
( # group and capture to \1:
@ # '@'
\w+ # word characters (a-z, A-Z, 0-9, _) (1 or
# more times (matching the most amount
# possible))
) # end of \1
\s* # whitespace (\n, \r, \t, \f, and " ") (0 or
# more times (matching the most amount
# possible))
( # group and capture to \2:
[^\n]* # any character except: '\n' (newline) (0
# or more times (matching the most amount
# possible))
) # end of \2