39

我正在尝试将一长串文本截断到一定长度,但还想确保截断的结果以空格结尾。之后我还将附加一个省略号。

例如这个:

"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;
4

6 回答 6

47

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

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

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

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

<%= truncate item.description.squish, :length => 30, :separator => /\w/,
                                      :omission => "&hellip;" %>
于 2012-02-29T17:21:41.747 回答
44
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..."
于 2012-02-29T17:21:32.900 回答
7

@evfwcqcg 的回答非常好。我发现它没有很好地工作时

  1. 该字符串包含其他非空格非字母数字字符。
  2. 字符串比所需长度短。

示范:

>> 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"

这是更喜欢它。

于 2013-09-04T01:19:02.607 回答
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"
于 2016-05-18T16:09:51.993 回答
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。是否应保留空格?- 目前他们是。
  • 与上面相同,但末尾的空格超过了 30 个限制。就像 ( s= "Twentyseven chars long text ") 中一样 - 目前所有结尾的空格都被截断并添加了省略号。
于 2016-10-06T23:41:22.193 回答
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..." 
于 2014-04-18T17:15:49.333 回答