除了最后一个单词之外,我如何匹配字符串中的每个单词?

时间:2016-09-30 23:33:00

标签: ruby regex

我有以下字符串:

Chicago CPA
New York CPA
West Virginia Accountant

我如何一直切断字符串中的最后一个单词(和前面的空格),保留最后一个单词之前的所有其他单词?

因此上述数据集的正确版本为:

Chicago
New York
West Virginia

此外,是否可以在Rubular上测试匹配组,还是可以使用另一个在线正则表达式编辑器/测试器来测试具有匹配组的正则表达式?

修改1

理论上很多答案都很棒。我读了它们,我理解它们,然后用香草串测试它们,它们似乎有效。但是当我在我的数据上尝试它时,它并没有。我被困了一段时间,我才明白为什么。

这是我正在处理的HTML:

<h1 class="search-term">
   Chicago&nbsp;<strong>Cpa</strong>
</h1>

所以这个文本,我试图在这上面进行字符串操作:

Chicago&nbsp;<strong>Cpa</strong>

所以当我尝试下面的每个答案时会发生什么。

@达山&#39; S:

[56] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text
=> "Chicago Cpa"
[57] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text.class
=> String
[58] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text.match(/(.*) \w+\z/)[1]
NoMethodError: undefined method `[]' for nil:NilClass
from (pry):57:in `<class:PageCrawler>'
[59] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text[/.*(?=\s\w+\z)/]
=> nil

@Lucas自己的:

[60] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text
=> "Chicago Cpa"
[61] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text.class
=> String
[62] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text.split()[0...-1].join(' ')
=> ""

@ Eric自己的:

[65] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text
=> "Chicago Cpa"
[66] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text.class
=> String
[67] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text.split().reverse.drop(1).reverse.join(" ")
=> ""

@ Casimir自己(实际上到目前为止这是最好的):

[68] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text
=> "Chicago Cpa"
[69] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text.class
=> String
[70] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text.sub(/\W+\w+\W*$/, '')
=> "Chicago"

@Santosh自己的:

[71] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text
=> "Chicago Cpa"
[72] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text.class
=> String
[73] pry(YPCrawler::PageCrawler)> @document.css('header h1.search-term').first.text[/(.*)\s/,1]
=> nil

我很抱歉没有早点这样做,但我没想到这是一个问题。

6 个答案:

答案 0 :(得分:4)

我将在前言中说我对正则表达式并不是特别擅长,而且我不确定是否在我的头脑中(我也不倾向于基准或认真思考)这是否会倾向于效率比@ LucasP的非正则表达式更高或更低。但这是我想到的显而易见的方法:

s.match(/(.*) \w+\z/)[1]

在字符串的末尾匹配一个或多个以空格开头的单词字符,并将之前的所有内容放入您随后抓取的组中。

data = ['Chicago CPA',
        'New York CPA',
        'West Virginia Accountant']

data.map{|s| s.match(/(.*) \w+\z/)[1]}
# => ["Chicago", "New York", "West Virginia"]

编辑: @CarySwoveland建议的这种方法的变体是使用超前表达式来忽略我们想要丢弃的部分,而不是我最初的方法将我们想要的部分放入我们随后访问的捕获组。以下是该方法的一个版本:

data.map{|s| s[/.*(?=\s\w+\z)/]}
# => ["Chicago", "New York", "West Virginia"]

编辑2 :根据您添加的信息,现在很清楚您遇到的问题是您有不间断的空格,即使与\s匹配也不匹配({ {1}}仅匹配ASCII空格,相当于\s)。因此,使用POSIX括号表达式[ \t\r\n\f]或明确匹配[[:space:]]非空中空格字符可以正常工作,假设所有空格都是非中断空格。我更喜欢前者,因为有时你可能会有其他空格:

\u00A0

答案 1 :(得分:2)

实现这一目标的一种方法如下:

myString.split()[0...-1].join(' ')

其中myString是您要在其上执行此操作的每个字符串。

  1. 首先,您将从字符串拆分为包含每个单词的列表。

  2. 然后选择包含除最后一个元素之外的所有元素的子列表。

  3. 最后你从列表回到字符串。

答案 2 :(得分:1)

假设您有多个单词,则可以使用替换词:

'West Virginia Accountant'.sub(/\W+\w+\W*$/, '')

答案 3 :(得分:0)

"New York Accountant".split().reverse.drop(1).reverse.join(" ")

答案 4 :(得分:0)

尝试以下。

str = ['Chicago CPA', 'New York CPA', 'West Virginia Accountant']

str.map{|s| s[0...s.rindex(' ')]}

输出:["Chicago", "New York", "West Virginia"]

使用Regexp。

str2 = "West Virginia Accountant"
p str2[/(.*)\s/,1]

输出:"West Virginia"

答案 5 :(得分:0)

您可以使用正则表达式/^(.*)\s+\w+\s*$/捕获除了最后一个字之外的所有内容:

示例:

str =  <<~EOF
        Chicago CPA
        New York CPA
        West Virginia Accountant
EOF

str.each_line do |line|
        puts line.match(/^(.*)\s+\w+\s*$/).captures.first
end

输出:

Chicago
New York
West Virginia