Ruby:子串到一定长度,也在子串中持续空格

时间:2012-02-29 17:12:31

标签: ruby string ruby-on-rails-4

我试图将一长串文本截断到一定长度,但也希望确保截断的结果以空格结尾。我之后也会附加一个省略号。

例如:

"This is a very long string that has more characters than I want in it."

成为这个:

"This is a very long string that..."

我从这开始,但显然这并不涉及在空格上结束字符串的问题。

<%= item.description[0..30] %>&hellip;

6 个答案:

答案 0 :(得分:41)

如果您使用的是Rails 4+,则应使用内置的truncate辅助方法,例如:

<%= truncate item.description, length: 30, separator: /\w+/ %>

字符串“...”将附加到截断的文本;要指定其他字符串,请使用:omission选项,例如omission: "xxx"

对于Rails 3.x,:separator选项必须是字符串。在许多情况下给予:separator => " "会很好,但只能抓住空格而不是其他空格。一个折衷方案是使用String#squish,它用一个空格替换所有空白序列(并且还修剪前导和尾随空格),例如: "foo\n\tbar ".squish会产生"foo bar"。它看起来像这样:

<%= truncate item.description.squish, :length => 30, :separator => /\w/,
                                      :omission => "&hellip;" %>

答案 1 :(得分:40)

s[0..30].gsub(/\s\w+\s*$/, '...')

原始答案在30个字符子字符串以空白字符结尾的情况下不起作用。这解决了这个问题。

>> desc="This is some text it is really long"

>> desc[0..30].gsub(/\s\w+$/,'...')
"This is some text it is really "

>> desc[0..30].gsub(/\s\w+\s*$/,'...')
"This is some text it is..."

答案 2 :(得分:7)

@ evfwcqcg的回答非常好。

时发现它效果不佳
  1. 该字符串包含非空格而非字母数字的其他字符。
  2. 字符串短于所需长度。
  3. 演示:

    >> s = "How about we put some ruby method Class#Method in our string"
    => "How about we put some ruby method Class#Method in our string"
    >> s[0..41].gsub(/\s\w+\s*$/, '...')
    => "How about we put some ruby method Class#Me"
    >> s[0..999].gsub(/\s\w+\s*$/, '...')
    => "How about we put some ruby method Class#Method in our..."
    

    这不是我的预期。

    以下是我用来解决此问题的方法:

    def truncate s, length = 30, ellipsis = '...'
      if s.length > length
        s.to_s[0..length].gsub(/[^\w]\w+\s*$/, ellipsis)
      else
        s
      end
    end
    

    进行测试时,输出结果如下:

    >> s = "This is some text it is really long"
    => "This is some text it is really long"
    >> truncate s
    => "This is some text it is..."
    

    仍然按预期行事。

    >> s = "How about we put some ruby method Class#Method in our string"
    => "How about we put some ruby method Class#Method in our string"
    >> truncate s, 41
    => "How about we put some ruby method Class..."
    >> truncate s, 999
    => "How about we put some ruby method Class#Method in our string"
    

    这更像是它。

答案 3 :(得分:3)

desc.gsub(/([\w\s]{30}).+/,'\1...')

扩展@evfwcqcg的答案,这是一个纯正的正则表达式,可以解决尾随空格的问题。

irb(main):031:0> desc="This is some text it is really long"
irb(main):033:0> desc.gsub(/([\w\s]{30}).+/,'\1...')
=> "This is some text it is really..."
irb(main):034:0> desc="This is some text it is really"
=> "This is some text it is really"
irb(main):035:0> desc.gsub(/([\w\s]{30}).+/,'\1...')
=> "This is some text it is really"
irb(main):036:0> desc="This is some text it is real"
=> "This is some text it is real"
irb(main):037:0> desc.gsub(/([\w\s]{30}).+/,'\1...')
=> "This is some text it is real"

答案 4 :(得分:1)

我很惊讶没有一个答案是真的正确(或者使用rails helper限制),虽然这是一个非常古老的问题,所以这里是解决方案。

让我们先明确制定目标。我们希望将字符串s截断为30个字符,如果它不能完全适合,也可以删除最后一个单词。我们还希望从结果中截断尾随空格并添加省略号,如果文本缩短了。

如果文本比限制更长,则缩短就像

一样简单
s[0,s.rindex(/\s/,30)].rstrip + '...'

如果我们想要整个结果最多30个字符,那么就像从30减去椭圆的长度一样简单。因为我们使用三个点(而不是一个三点字符)而不是我们需要

s[0,s.rindex(/\s/,27)].rstrip + '...'

最终结果(测试是否需要截断)是:

if s.length<=30
  s
else
  s[0,s.rindex(/\s/,27)].rstrip + '...'
end

多数民众赞成。

注意:当所需的结果不明显时,有一些阴暗的情况。他们在这里:

  • 如果字符串以大量空格(s= "Helo word ")结尾但是小于30.应该保留空格吗? - 目前他们是。
  • 与上面相同,但最后的空格超过了限制o 30.与(s= "Twentyseven chars long text ")类似 - 目前所有空格和末尾都被截断并添加了省略号。 < / LI>

答案 5 :(得分:0)

class String
  def trunca(length=100, ellipsis='...')
    self.length > length ? self[0..length].gsub(/\s*\S*\z/, '').rstrip+ellipsis : self.rstrip
  end
end

示例:

-bash> irb
2.0.0p247 :001 > class String
2.0.0p247 :002?>     def trunca(length=100, ellipsis='...')
2.0.0p247 :003?>         self.length > length ? self[0..length].gsub(/\s*\S*\z/, '').rstrip+ellipsis : self.rstrip
2.0.0p247 :004?>       end
2.0.0p247 :005?>   end
 => nil 
2.0.0p247 :006 > s = "This is a very long string that has more characters than I want to display."
 => "This is a very long string that has more characters than I want to display." 
2.0.0p247 :007 > s.trunca(20)
 => "This is a very long..." 
2.0.0p247 :008 > s.trunca(31)
 => "This is a very long string that..."