分解以下代码以了解我的正则表达式和gsub
理解:
str = "abc/def/ghi.rb"
str = str.gsub(/^.*\//, '')
#str = ghi.rb
^
:字符串的开头
\/
:/
^.*\/
:字符串
/
开始到最后一次出现的所有内容
我对表达的理解是对吗?
.*
如何正常工作?
答案 0 :(得分:4)
您的一般理解是正确的。整个正则表达式将匹配abc/def/
,而String#gsub
将替换为空字符串。
但是,请注意String#gsub
不会更改字符串。这意味着str
将包含替换后的原始值("abc/def/ghi.rb"
)。要对其进行更改,您可以使用String#gsub!
。
.*
如何工作 - 正则表达式引擎使用的算法称为backtracking。由于.*
是贪婪的(会尝试匹配尽可能多的字符),你可以认为这样的事情会发生:
第1步:
.*
匹配整个字符串abc/def/ghi.rb
。之后\/
尝试匹配正斜杠,但失败(没有任何东西可以匹配)。.*
必须回溯 第2步:.*
匹配除最后一个字符之外的整个字符串 -abc/def/ghi.r
。之后\/
尝试匹配正斜杠,但失败(/ != b
)。.*
必须回溯 第3步:.*
匹配除最后两个字符之外的整个字符串 -abc/def/ghi.
。之后\/
尝试匹配正斜杠,但失败(/ != r
)。.*
必须回溯 的 ... 强>
第n步:.*
匹配abc/def
。之后\/
尝试匹配正斜杠并成功。匹配在这里结束。
答案 1 :(得分:2)
不,不完全。
^
:行开头\/
:转义斜杠(转义字符仅为\
)^.*\/
:从一行的开头到字符串中最后一次出现/
的所有内容 .*
取决于正则表达式的模式。在单行模式中(即,没有m
选项),它表示零或更多非换行符的最长可能序列。在多行模式下(即使用m
选项),它表示零个或多个字符的最长序列。
答案 2 :(得分:1)
您的理解是正确的,但您还应注意最后一条陈述是正确的,因为:
Repetition is greedy by default: as many occurrences as possible
are matched while still allowing the overall match to succeed.
引自Regexp文档。
答案 3 :(得分:0)
是。简而言之,它匹配以文字.*
(/
)结尾的任意数量的任何字符(\/
)。
gsub
将匹配替换为第二个参数(空字符串''
)。
答案 4 :(得分:0)
你的正则表达式没有错,但File.basename(str)可能更合适。
要阐述@Stefen所说的内容:看起来你正在处理一个文件路径,这会让你的问题成为一个XY问题,当你问X时应该问Y:而不是如何使用和理解正则表达式,问题应该是使用什么工具来管理路径。
使用已经编写的语言附带的代码,而不是滚动自己的代码:
str = "abc/def/ghi.rb"
File.basename(str) # => "ghi.rb"
File.dirname(str) # => "abc/def"
File.split(str) # => ["abc/def", "ghi.rb"]
您希望利用File的内置代码的原因是它考虑了* nix风格的操作系统和Windows中的目录分隔符之间的区别。在启动时,Ruby会检查操作系统并将File::SEPARATOR
常量设置为操作系统所需的内容:
File::SEPARATOR # => "/"
如果您的代码从一个系统移动到另一个系统,如果您使用内置方法,它将继续工作,而使用正则表达式将立即中断,因为分隔符将是错误的。