【问题标题】:How to replace unknown whitespace on string如何替换字符串上的未知空格
【发布时间】:2021-01-30 10:51:03
【问题描述】:

我从具有某种间距的 API 获取字符串 string2。在string2 上,空格不是常规空格,我什至不知道它们是否是制表符,但如果我尝试替换它们仍然不等于间隔string1

// This string has normal spaces charCodeAt(4) displays '32'
const string1 = 'long string with spaces'
// This string has different spaces charCodeAt(4) displays '160'
const string2 = 'long string with spaces'.replace(/\s+/g, ' ')

console.log(string1)
console.log(string2)
console.log(string1 === string2)

--- 更新

问题是我在string1 上混合了普通空格和不间断空格,因此无论我更改多少string2,它都永远不会等于string2

由于我确实可以控制string1,因此我已将其更正为具有正常空格,现在它可以工作了。

【问题讨论】:

  • 这将返回真而不是假
  • This answer 可能会有所帮助。
  • 这可能意味着您在任一字符串中都有一些不可见的字符(可能在非 ASCII 范围内)。我把你的代码变成了一个sn-p,它返回true。因此,请在您的问题中提供重现该问题的代码。
  • 检查字符的.charCode()。您会发现一些代码为 160 的“空格”是不间断空格 ( )
  • 确实,对 string2 的检查表明它没有常规空格。如果您对其应用相同的替换,则字符串将相等。

标签: javascript


【解决方案1】:

代码点160 (\u00a0) 是一个不间断的空格。

如果您是don't need to support IE,则可以使用Unicode property escape /\p{White_Space}+/gu 作为/\w+/ 的Unicode 感知替代品。这将匹配 \u00a0 以及任何其他空白字符。

如果您需要支持 IE,您可以生成自己的空白匹配正则表达式,使用 确实 支持 Unicode 属性转义的环境。例如,在 Chrome 浏览器控制台中运行以下命令:

const toUnicodeEscape = x => '\\u' + x.toString(16).padStart(4, '0')

const last = arr => arr.slice(-1)[0]

const charGroupings = [...new Array(0xffff).keys()]
    .map(k => String.fromCodePoint(k))
    .filter(x => /^\p{White_Space}+$/u.test(x))
    .map(x => x.codePointAt(0))
    .reduce((acc, n) => {
        const prev = last(acc)

        if (prev && last(prev) === n - 1) {
            prev.push(n)
        } else {
            acc.push([n])
        }

        return acc
    }, [])
    .map(x => x.length <= 2
        ? x.map(toUnicodeEscape).join('')
        : `${toUnicodeEscape(x[0])}-${toUnicodeEscape(last(x))}`)
    .join('')

new RegExp(`[${charGroupings}]+`, 'g')

生成正则表达式/[\u0009-\u000d\u0020\u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]+/g,它完全等同于/\p{White_Space}+/gu

【讨论】:

    【解决方案2】:

    我可以把charCode超过126的所有字符变成空格键

    function formatWhiteSpaces(string){
      return string.split('')
      .map(a=>{ if(a.charCodeAt()<127){return(a)}return(" ") }) //when charcode of something > 126 (127+), it returns strange characters.. String.fromCharCode(160) returns something looking like " " and String.fromCharCode(173 returns something looking like "")
      .join('')
    }
    var string1 = formatWhiteSpaces('long string with spaces')
    var string2 = formatWhiteSpaces('long string with spaces')
    console.log(string1)
    console.log(string2)
    console.log(string1 === string2)

    以防万一我真的把想要的字符变成了空格键,我可以让它非常具体(因为只有 String.fromCharCode(160) 使空格键看起来像东西)

    function formatWhiteSpaces(string){
      return string.split('')
      .map(a=>{
        if(a.charCodeAt()==160){return(" ")} //160 similar to " "
        if(a.charCodeAt()==173){return("")}//173 similar to ""
        return(a)
      })
      .join('')
    }
    var string1 = formatWhiteSpaces('long string with spaces')
    var string2 = formatWhiteSpaces('long string with spaces')
    console.log(string1)
    console.log(string2)
    console.log(string1 === string2)

    【讨论】:

      【解决方案3】:

      如果字符串包含单词和空格(不同),我们可以提取单词并重建字符串然后比较。

      const cleanStr = str => [...str.matchAll(/\w+/g)].map(x => x[0]).join(' ')
      
      // This string has normal spaces charCodeAt(4) displays '32'
      const string1 = 'long string with spaces'
      // This string has different spaces charCodeAt(4) displays '160'
      const string2 = 'long string with spaces'
      
      console.log(string1)
      console.log(string2)
      console.log(cleanStr(string1) === cleanStr(string2))

      【讨论】:

      • 这对于空格 const cleanStr = str =&gt; str.replace(/\s+/g, ' ') 也同样有效,无需将字符串转换为数组
      猜你喜欢
      • 1970-01-01
      • 2019-05-16
      • 1970-01-01
      • 2012-07-29
      • 2013-11-21
      • 2019-04-16
      • 1970-01-01
      • 2013-05-09
      • 2020-12-19
      相关资源
      最近更新 更多