提问人:Donslaught 提问时间:7/28/2023 更新时间:7/28/2023 访问量:61
在 Rails 中从字符串中间提取子字符串
Extracting substring from the middle of a string in Rails
问:
我正在尝试从作为字符串返回的类类型中提取子字符串:
'::Pos::EmailNotice'
'Pos::EmailNotice'
'::Pos::CallNotice'
'Pos::CallNotice'
因此,如果我得到一个字符串“Pos::{type}Notice”,我需要以{type}结束。
我尝试使用和,但我希望它比这更动态,以防万一命名空间被更改或我们将来添加更多类型的通知。#slice
#delete_prefix
#delete_suffix
我尝试在这里搜索,但我找不到任何答案来解释如何在这样的情况下提取文本。
答:
0赞
Andre Wildberg
7/28/2023
#1
测试字符串
str = ['::Pos::EmailNotice', 'Pos::EmailNotice',
'::Pos::CallNotice', 'Pos::CallNotice', 'Pos::CallText']
用gsub
str.map {|i| i.gsub /.*::|(Notice|Text)$/, ""}
["Email", "Email", "Call", "Call", "Call"]
1赞
smathy
7/28/2023
#2
假设它总是以 结尾,那么这可能是最简单的:Notice
main> %w[ ::Pos::EmailNotice Pos::EmailNotice ::Pos::CallNotice Pos::CallNotice ].map do |s|
main> s.match(/([^:]+)Notice/)[1]
main> end
["Email", "Email", "Call", "Call"]
这基本上是说“所有非':'字符在'通知'之前”。
评论
1赞
Stefan
7/28/2023
还有,当没有找到匹配项时,它只是返回。您可能希望添加一个锚点来匹配字符串的末尾。s[/([^:]+)Notice/, 1]
nil
\z
0赞
smathy
7/28/2023
哇,TIL,谢谢!我一直在做一件事,但这是一个非常好的语法。if x = s.match ... x[1]
1赞
Cary Swoveland
7/28/2023
#3
arr = [ "::Pos::EmailNotice",
"Pos::EmailNotice",
"::Pos::CallNotice",
"Pos::CallNotice"
]
arr.map { |str| str[/[^:]*(?=Notice\z)/] }
#=> ["Email", "Email", "Call", "Call"]
该演示采用 PCRE 正则表达式引擎。虽然在某些方面与 Ruby 的 Onigmo 正则表达式引擎不同,但在这种情况下,它们给出了相同的结果。我使用了行尾锚点 () 而不是字符串末尾锚点 () 来针对多个字符串测试表达式。$
\z
它使用带有正则表达式作为参数的 String#[] 方法。
正则表达式为“匹配除 () 以外的零个或多个 () 字符,在字符串 () 末尾后跟文字”Notice”。*
^
\z
(?=Notice\z)
是一种积极的展望。
您可能希望将光标悬停在链接处正则表达式的每个部分上,以获取其功能的说明。
1赞
Stefan
7/28/2023
#4
Rails 提供了 String#demodulize
来剥离模块中的命名空间:
'::Pos::EmailNotice'.demodulize #=> "EmailNotice"
'Pos::EmailNotice'.demodulize #=> "EmailNotice"
'::Pos::CallNotice'.demodulize #=> "CallNotice"
'Pos::CallNotice'.demodulize #=> "CallNotice"
您可以将其与 delete_suffix!
一起使用,例如
string = '::Pos::EmailNotice'
string.demodulize.delete_suffix!('Notice')
#=> "Email"
另一种方法是将字符串转换为实际的类,并让它实现一个你可以调用的方法,例如:type
module Pos
class EmailNotice
def self.type
:email
end
end
end
然后你可以使用 Rails 的 String#constantize
:
'::Pos::EmailNotice'.contantize.type #=> :email
'Pos::EmailNotice'.contantize.type #=> :email
或者通过 Module#const_get
使用纯 Ruby:
Object.const_get('::Pos::EmailNotice').type #=> :email
Object.const_get('Pos::EmailNotice').type #=> :email
评论