为了理解我的正则表达式和gsub
函数,将下面的代码拆开:
str = "abc/def/ghi.rb"
str = str.gsub(/^.*\//, '')
#str = ghi.rb
^
:表示字符串开头
\/
:是转义字符,用来转义 /
^.*\/
:从字符串开始到最后一个 /
之间的所有内容
我的理解正确吗?
.*
到底是如何工作的?
abc/def/
,并且String#gsub
将用空字符串替换它。String#gsub
不会直接更改原始字符串。这意味着在替换后,str
将包含原始值("abc/def/ghi.rb"
)。要直接更改原始字符串,您可以使用String#gsub!
。.*
如何工作 - 正则表达式引擎使用的算法称为回溯。由于.*
是贪婪的(尝试尽可能多地匹配字符),您可以认为会发生以下情况:
步骤1: .*
匹配整个字符串abc/def/ghi.rb
。之后,\/
尝试匹配一个斜杠,但失败了(没有剩余的内容可以匹配)。.*
必须回溯。
步骤2: .*
匹配除最后一个字符外的整个字符串 - abc/def/ghi.r
。之后,\/
尝试匹配一个斜杠,但失败了(/ != b
)。.*
必须回溯。
步骤3: .*
匹配除最后两个字符外的整个字符串 - abc/def/ghi.
。之后,\/
尝试匹配一个斜杠,但失败了(/ != r
)。.*
必须回溯。
...
步骤n: .*
匹配abc/def
。之后,\/
尝试匹配一个斜杠并成功。匹配到此结束。不完全正确。
^
:行首\/
:转义斜杠(转义字符为 \
)^.*\/
:从行首到字符串中最后一个 /
的所有内容.*
取决于正则表达式的模式。在单行模式下(即没有 m
选项),它表示零个或多个非换行符的最长可能序列。在多行模式下(即使用 m
选项),它表示零个或多个字符的最长可能序列。
Repetition is greedy by default: as many occurrences as possible
are matched while still allowing the overall match to succeed.
str = "abc/def/ghi.rb"
File.basename(str) # => "ghi.rb"
File.dirname(str) # => "abc/def"
File.split(str) # => ["abc/def", "ghi.rb"]
File::SEPARATOR
常量设置为操作系统所需的内容:File::SEPARATOR # => "/"
是的。简而言之,它匹配以字面意义的/
(\/
)结尾的任意数量的任何字符(.*
)。
gsub
将匹配项替换为第二个参数(空字符串''
)。
^
是行首锚点。字符串开头是\A
。对于单行字符串,两者的作用相同。 - undur_gongorFile.basename(str)
可能更合适。 - Stefan