【问题标题】:How to find a substring anywhere in a string如何在字符串中的任意位置查找子字符串
【发布时间】:2017-12-06 01:41:10
【问题描述】:

这应该很容易,但我觉得很难。

我只想找出一个子字符串是否存在于字符串中的任何位置。就我而言,产品标题中是否存在网站名称。

我的代码是这样的:

#FindNoCase("Amazon.com", "Google Chromecast available at Amazon")#

上面返回一个0,这是正确的,因为主字符串中不存在整个子字符串“Amazon.com”。但其中一些确实如此,即“亚马逊”部分。

我怎样才能实现我正在尝试做的事情,即查看主字符串中是否存在任何子字符串(长度至少超过 2 个字符)?

所以我需要像 FindOneOf() 这样的东西,但实际上“至少找到三个”。然后它应该查看产品标题中的“Amazon”一词,并检查“Amazon.com”序列中是否存在至少 3 个字符。当它看到“Ama”存在时,它只需要返回一个true 值。可以使用现有的内置函数以某种方式完成吗?

更新:非常简单的解决方案。我使用了左(“亚马逊”,3)。

【问题讨论】:

  • 返回什么? 0 以外的任何数字都表示匹配。它应该返回 25 左右的值(Amazon 位置在字符串中开始。
  • 非常抱歉,我输入的值不正确。我已更新我的帖子以显示正确的值。
  • 您正在搜索Amazon.com,但它不在字符串中。
  • 没错。我想我的问题应该改写,以找出主字符串中是否存在任何子字符串。那将是 FindOneOf() 但它会检查单个字符。所以它会返回 1,因为字母 A 存在于第一个位置。

标签: coldfusion coldfusion-11


【解决方案1】:

误报有很多危险,比如有人在购买阿拉巴马州的国旗。

由于店铺名称中包含空格,这有点棘手(Wal Mart 经常用空格来写)。

如果您的字符串始终包含at [store],您可以通过查找句子中的最后一个 at 并通过切掉其他所有内容来创建一个字符串来提取商店名称。

因为它只查找出现在整个单词中的at,所以使用Beats AudioSam's Meat Shop 等商店名称没有危险。我想不出任何名称中带有 at 这个词的商店。虽然这在技术上会出错,但风险要低得多,您可以对此类商店名称进行预先替换。

<cfset mystring = "Google Chromecast available at Amazon">
<cfset SellerName = REReplaceNoCase(mystring,".*\b(?:at)\b(?!.*\b(?:at)\b)\s*","")>
<cfoutput>Seller: #Sellername#</cfoutput>

然后您可以更安全地进行比较。


根据您的评论,如果您知道所有可能的模式,您仍然可以根据需要获取数据(误报可能是令人尴尬的或灾难性的,具体取决于操作)。如果你知道你正在使用的商店,你可以使用正则表达式来提取这样的字符串

<cfset mystring = "Google Chromecast available at Amazon.co.uk">
<cfset SellerName = REReplaceNoCase(mystring,".*\b((Google|Amazon|Wal[\W]*Mart|E[\W]*bay)(\.[a-z]+)*)\b","\1")>
<cfoutput>Seller: #Sellername#</cfoutput>

您需要更新的唯一部分是管道分隔列表您可以将 K-Mart 添加为 K[\W]*Mart [\W]* 允许任何特殊字符或空格,因此它涵盖 kMart、K-Mart、k*Mart,但是不是 Kwik-E-Mart。


更新 #2,每增加一个 cmets

<cfset mystring = "Google Chromecast available at Toys-R-US">
<cfset SellerNameRE = REReplace(rsProduct.sellername,"[\W]+","[\W]*","ALL")>
<cfset TheSellerName = REReplaceNoCase(mystring,".*\b((#sellernameRE#)(\.[a-z]+)*)\b","\1")>
<cfoutput>Seller: #TheSellername# (#SellerNameRE#)</cfoutput>

这会将任何符号替换为通配符,这样就不需要符号了,这样即使是 Wal*Mart,它仍然会匹配 WalMart。

您还可以使用“正则表达式名称”加载单独的列,这样您就不必每次都这样做了。

所以你的桌子看起来像

SellerID    SellerName    RegexName
1           Wal-Mart      Wal[\W]*Mart
2           Toys-R-US     Toys[\W]*R[\W]*US

<cfset mystring = "Google Chromecast available at Toys-R-US">
<cfset TheSellerName = REReplaceNoCase(mystring,".*\b((#rsProduct.RegexName#)(\.[a-z]+)*)\b","\1")>
<cfoutput>Seller: #TheSellername# (#SellerNameRE#)</cfoutput>

【讨论】:

  • 不幸的是,它并不总是以“at storename”结尾。它可能类似于“Amazon Prime 现在 50% 的折扣”。所以我们把亚马逊放在标题的前面。
  • @volumeone 查看我的编辑,它仍然是可能的。虽然同样,可能会出现误报(它将选择最后一个匹配项。在字符串“Google is sell Amazon Kindle”中,它将选择 Amazon。现在,如果您将第一个 .* 更改为 .*?,它拿起谷歌。
  • 这真的很有趣。 SellerName 和 ProductTitle 实际上来自 cfquery 记录集。那么如何实现正则表达式来检查 rsProduct.SellerName 而不是 Google|Amazon|Wal[\W]*Mart 等中的值?抱歉,我的正则表达式技能非常基础
  • @volumeone 你有特定的卖家,还是有很多?理想情况下,您会使用管道分隔列表,但是,要执行您想要的操作,您可以使用&lt;cfset TheSellerName = REReplaceNoCase(mystring,".*\b((#rsProduct.sellername#)(\.[a-z]+)*)\b","\1")&gt;。 (我将变量名称更改为 TheSellerName,因为我看到您将其用作查询列名称)
  • 有数百个卖家。并且不断添加更多内容。如果我在“主”页面上执行此操作,该页面以 15 个批次为单位列出产品,是否会对性能产生重大影响。所以它首先加载 15 个,然后您可以分页到下一个 15 个,依此类推。我问这个是因为我必须进行正则表达式替换,然后运行 ​​FindNoCase() 函数。
【解决方案2】:

这样解决了

#FindNoCase(left("Amazon.com", 3), "Google Chromecast available at Amazon")#

是的,如果卖家名称少于 3 个字符,它可能无法满足我的需求。但我认为它很少见就可以了。

【讨论】:

    猜你喜欢
    • 2012-05-21
    • 1970-01-01
    • 2014-05-06
    • 2012-08-03
    • 2017-03-27
    • 2015-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多