JavaScript 字符串说明的正则表达式开始 + str.replace()
JavaScript Regex start of string clarification + str.replace()
有一个关于字符串正则表达式锚标记 ^
开头的问题。
我试图清理一个字符串以检查它是否是回文,并找到了使用正则表达式的解决方案,但我无法理解我为字符串锚标记开头找到的解释:
据我了解:
^
表示后面的任何表达式都必须匹配,从字符串的开头开始。
问题:
为什么下面两个输出之间存在差异:
1)
let x = 'A man, a plan, a canal: Panama';
const re = new RegExp(/[^a-z]/, 'gi');
console.log(x.replace(re, '*'));
输出:A*man**a*plan**a*canal**Panama
VS.
2)
let x = 'A man, a plan, a canal: Panama';
const re = new RegExp(/[a-z]/, 'gi');
console.log(x.replace(re, '*'));
输出:* ***, * ****, * *****: ******
VS.
3)
let x = 'A man, a plan, a canal: Panama';
const re = new RegExp(/^[a-z]/, 'gi');
console.log(x.replace(re, '*'));
输出:* man, a plan, a canal: Panama
如果我对上述每个案例的解释有误,请告诉我:
1) 对此感到困惑。如果它匹配 [a-z]
不区分大小写 + 全局查找的字符 class,字符串锚点的开头 ^
表示它必须在每个字符串的开头匹配,如果不是 return 句子中的所有单词?由于每个单词都是 [a-z]
不敏感字符的匹配项,这些字符出现在每个全局查找迭代的每个字符串的开头?
(即
- 在开头找到 "A"
- 然后在下一次迭代中,它应该开始搜索剩余的字符串“man”
- 找到 space...并继续搜索 "man"?
- 等等……
问:为什么当我调用 replace
时它只针对非 alpha 内容?在这种情况下,我应该将 ^
视为反转 [a-z]
吗?
2) 这看起来很简单,找到所有出现的 [a-z]
并将它们替换为开头。 1)的反例??
3) 也对这个一头雾水。我不确定这与 1) 有何不同。
/^[a-z]/gi
对我来说意味着:"starting at the start of the string being looked at, match all alpha characters, case insensitive. Repeat for global find".
相比于:
1) /[^a-z]/gi
对我来说意味着:"match all character class that starts each line with alpha character. case insensitive, repeat search for global find."
意思是他们的意思完全一样@_@。请让我知道我对上述情况的理解有何偏差。
您的第一个表达式 [^a-z]
匹配除字母、小写字母以外的任何内容,因此这就是为什么当您用 *
替换所有特殊字符(如空格、逗号)时和冒号被替换。
您的第二个表达式 [a-z]
匹配任何字母小写字母,因此提到的特殊字符不会被 *
替换。
您的第三个表达式 ^[a-z]
匹配字符串开头的小写字母,因此只有第一个字母被替换为 *
。
对于前两个表达式,全局标志 g
确保替换所有与指定模式匹配的字符,无论它们在字符串中的位置如何。然而,对于第三个模式,由于 ^
将模式锚定在字符串的开头,因此仅替换第一个字母。
正如您所提到的,i
标志确保不区分大小写,因此所有三种模式都适用于小写和大写字母,从 a
到 z
和 A
到 Z
.
字符^
因此有两个含义:
- 它否定字符集中的字符。
- 它在字符串的开头断言位置。
^ denotes that whatever expression that follows must match, starting from the beginning of the string.
只有当它是正则表达式中的第一件事时才会这样;它在其他地方使用时有其他用途:
/[^a-z]/gi
在上面的正则表达式中,^
而不是 指示将匹配锚定到字符串的开头;它会反转 []
的其余内容——所以上面的正则表达式将匹配任何单个字符 除了 a-z。由于您使用的是 g
标志,它将对字符串中的所有字符重复匹配。
/[a-z]/gi
上面没有反转,所以将匹配 a-z 中任何字符的单个实例(并且再次因为 g
标志将重复匹配所有这些实例。)
/^[a-z]/gi
在最后一个示例中,插入符号将匹配锚定到字符串的开头;括号内的部分将匹配任何单个 a-z 字符。 g
标志仍在使用中,因此正则表达式将尝试继续匹配字符串后面的更多字符——但除第一个字符外,其中的 none 将满足锚定到开始的要求, 所以这将最终只匹配第一个字符(如果它在 a-z 内),就像 g
标志没有被使用一样。
(当在正则表达式的开头或 []
组的开头以外的任何地方使用时,^
将被视为文字 ^
。)
如果您尝试检测回文,您需要删除除字母字符以外的所有字符(并且可能希望将所有字符转换为相同的字母大小写,而不必检测 "P" = = "p":)
const isPalindrome = function(input) {
let str = input.toLowerCase().replace(/[^a-z]/g,'');
return str === str.split('').reverse().join('')
}
console.log(isPalindrome("Able was I, ere I saw Elba!"))
console.log(isPalindrome("No, it never propagates if I set a ”gap“ or prevention."))
console.log(isPalindrome("Are we not pure? “No, sir!” Panama’s moody Noriega brags. “It is garbage!” Irony dooms a man –– a prisoner up to new era."))
console.log(isPalindrome("Taco dog is not a palindrome."))
有一个关于字符串正则表达式锚标记 ^
开头的问题。
我试图清理一个字符串以检查它是否是回文,并找到了使用正则表达式的解决方案,但我无法理解我为字符串锚标记开头找到的解释:
据我了解:
^
表示后面的任何表达式都必须匹配,从字符串的开头开始。
问题:
为什么下面两个输出之间存在差异:
1)
let x = 'A man, a plan, a canal: Panama';
const re = new RegExp(/[^a-z]/, 'gi');
console.log(x.replace(re, '*'));
输出:A*man**a*plan**a*canal**Panama
VS.
2)
let x = 'A man, a plan, a canal: Panama';
const re = new RegExp(/[a-z]/, 'gi');
console.log(x.replace(re, '*'));
输出:* ***, * ****, * *****: ******
VS.
3)
let x = 'A man, a plan, a canal: Panama';
const re = new RegExp(/^[a-z]/, 'gi');
console.log(x.replace(re, '*'));
输出:* man, a plan, a canal: Panama
如果我对上述每个案例的解释有误,请告诉我:
1) 对此感到困惑。如果它匹配 [a-z]
不区分大小写 + 全局查找的字符 class,字符串锚点的开头 ^
表示它必须在每个字符串的开头匹配,如果不是 return 句子中的所有单词?由于每个单词都是 [a-z]
不敏感字符的匹配项,这些字符出现在每个全局查找迭代的每个字符串的开头?
(即
- 在开头找到 "A"
- 然后在下一次迭代中,它应该开始搜索剩余的字符串“man”
- 找到 space...并继续搜索 "man"?
- 等等……
问:为什么当我调用 replace
时它只针对非 alpha 内容?在这种情况下,我应该将 ^
视为反转 [a-z]
吗?
2) 这看起来很简单,找到所有出现的 [a-z]
并将它们替换为开头。 1)的反例??
3) 也对这个一头雾水。我不确定这与 1) 有何不同。
/^[a-z]/gi
对我来说意味着:"starting at the start of the string being looked at, match all alpha characters, case insensitive. Repeat for global find".
相比于:
1) /[^a-z]/gi
对我来说意味着:"match all character class that starts each line with alpha character. case insensitive, repeat search for global find."
意思是他们的意思完全一样@_@。请让我知道我对上述情况的理解有何偏差。
您的第一个表达式
[^a-z]
匹配除字母、小写字母以外的任何内容,因此这就是为什么当您用*
替换所有特殊字符(如空格、逗号)时和冒号被替换。您的第二个表达式
[a-z]
匹配任何字母小写字母,因此提到的特殊字符不会被*
替换。您的第三个表达式
^[a-z]
匹配字符串开头的小写字母,因此只有第一个字母被替换为*
。
对于前两个表达式,全局标志 g
确保替换所有与指定模式匹配的字符,无论它们在字符串中的位置如何。然而,对于第三个模式,由于 ^
将模式锚定在字符串的开头,因此仅替换第一个字母。
正如您所提到的,i
标志确保不区分大小写,因此所有三种模式都适用于小写和大写字母,从 a
到 z
和 A
到 Z
.
字符^
因此有两个含义:
- 它否定字符集中的字符。
- 它在字符串的开头断言位置。
^ denotes that whatever expression that follows must match, starting from the beginning of the string.
只有当它是正则表达式中的第一件事时才会这样;它在其他地方使用时有其他用途:
/[^a-z]/gi
在上面的正则表达式中,^
而不是 指示将匹配锚定到字符串的开头;它会反转 []
的其余内容——所以上面的正则表达式将匹配任何单个字符 除了 a-z。由于您使用的是 g
标志,它将对字符串中的所有字符重复匹配。
/[a-z]/gi
上面没有反转,所以将匹配 a-z 中任何字符的单个实例(并且再次因为 g
标志将重复匹配所有这些实例。)
/^[a-z]/gi
在最后一个示例中,插入符号将匹配锚定到字符串的开头;括号内的部分将匹配任何单个 a-z 字符。 g
标志仍在使用中,因此正则表达式将尝试继续匹配字符串后面的更多字符——但除第一个字符外,其中的 none 将满足锚定到开始的要求, 所以这将最终只匹配第一个字符(如果它在 a-z 内),就像 g
标志没有被使用一样。
(当在正则表达式的开头或 []
组的开头以外的任何地方使用时,^
将被视为文字 ^
。)
如果您尝试检测回文,您需要删除除字母字符以外的所有字符(并且可能希望将所有字符转换为相同的字母大小写,而不必检测 "P" = = "p":)
const isPalindrome = function(input) {
let str = input.toLowerCase().replace(/[^a-z]/g,'');
return str === str.split('').reverse().join('')
}
console.log(isPalindrome("Able was I, ere I saw Elba!"))
console.log(isPalindrome("No, it never propagates if I set a ”gap“ or prevention."))
console.log(isPalindrome("Are we not pure? “No, sir!” Panama’s moody Noriega brags. “It is garbage!” Irony dooms a man –– a prisoner up to new era."))
console.log(isPalindrome("Taco dog is not a palindrome."))