Гораздо лучше использовать парсер, даже с крошечным фрагментом, если только вы не уверены, что строка никогда не изменит формат, и вам не принадлежит процесс от начала до конца.
Тем не менее,чтобы удовлетворить ваши требования регулярных выражений, я бы использовал String.scan:
str = "lorem <tt>text1</tt> ipsum <tt>text2</tt>dolor si amet"
str.scan(%r{<tt>([^<]+)</tt>}).flatten # => ["text1", "text2"]
Просто чтобы показать, насколько просто использовать парсер:
require 'nokogiri'
doc = Nokogiri::HTML(str)
doc.css('tt').map(&:text) # => ["text1", "text2"]
Преимущество - гибкость и надежность,