将驼峰大小写字符串转换为烤肉串大小写的正则表达式
Regular rxpression to convert a camel case string into kebab case
function hyphenate(str) {
var replace = "-";
str = str.toLowerCase().replace(/[\s_\b]/g, replace);
console.log(str);
return str;
}
hyphenate("This Is Hyphenate"); // this-is-hyphenate
hyphenate("camelCaseString"); // camel-case-string
我正在尝试让我的代码生成第二个函数调用的结果,但尚未确定可以执行此操作的模式。如有任何帮助,我们将不胜感激。
在小写前尝试先行:
function hyphenate(str) {
return str.split(/[\s_\b]|(?=[A-Z])/).join('-').toLowerCase();
}
您可以使用捕获组获取小写字母后接大写字母,然后将整个字符串转换为小写字母:
str.replace(/([a-z])([A-Z])/g,"-").toLowerCase();
请注意,[\s_\b]
中的 \b
表示退格符。不确定您是否真的需要这个。
使用 ECMAScript 2018 中引入的后视功能更新了答案:
const re = /[\W_]+|(?<=[a-z0-9])(?=[A-Z])/g;
const strs = ['camelCaseString','This Is Hyphenate','This_Should_Hyphenate', '09Report'];
strs.forEach(str =>
console.log( str.replace(re, "-").toLowerCase() )
);
[\W_]+|(?<=[a-z0-9])(?=[A-Z])
正则表达式将匹配
[\W_]+
- 任何 1+ 个非单词和 _
个字符
|
- 或
(?<=[a-z0-9])(?=[A-Z])
- 小写 ASCII letter/digit 和大写 ASCII 字母之间的位置。
旧答案
我会使用有点不同的逻辑:在单词中的每个大写字母前添加一个连字符,然后替换并转为小写:
var re = /[\s_]+|([a-z0-9])(?=[A-Z])/g;
var str = 'camelCaseString<br/>This Is Hyphenate<br/>This_Should_Hyphenate';
var result = str.replace(re, "-").toLowerCase();
document.body.innerHTML += result;
解释:
[\s_]+
- 一个或多个空格或下划线
|
- 或者...
([a-z0-9])
-(第 1 组)小写字母或数字(因为 \B
不允许我们在 _
之后匹配大写字母,如果您添加 A-Z
想在每个大写字母前添加 -
)
(?=[A-Z])
- 对大写 ASCII 字母的测试(未使用,因为它 (?=[A-Z])
是先行,零宽度断言)。
这可能对您的要求有点矫枉过正,但希望这个答案能帮助任何试图将(几乎)任何字符串转换为烤肉串大小写的人:
const convertStringToKebebCase = str => str && str
.match(/[0-9]{1,}(?=\b)|[A-Z]{2,}(?=[A-Z][a-z]+|[0-9]|\b|_)|[A-Z]?[a-z]+|[A-Z]|[0-9]+/g)
.map(x => x.toLowerCase())
.join('-')
以下是上述函数的测试,因此您可以了解它的行为方式(我将函数重命名为 toKebeb
只是为了在此处更容易阅读):
// Lowercase
expect(toKebeb('path')).toEqual('path')
expect(toKebeb('PATH')).toEqual('path')
// Spaces
expect(toKebeb('path route')).toEqual('path-route')
expect(toKebeb('path route 0')).toEqual('path-route-0')
expect(toKebeb('123 path 4 route 567')).toEqual('123-path-4-route-567')
// Kebab
expect(toKebeb('path-route')).toEqual('path-route')
expect(toKebeb('PATH-ROUTE')).toEqual('path-route')
expect(toKebeb('path-route0')).toEqual('path-route-0')
expect(toKebeb('path-route-0')).toEqual('path-route-0')
expect(toKebeb('123-path-4-route-567')).toEqual('123-path-4-route-567')
expect(toKebeb('123-path-4-route-567')).toEqual('123-path-4-route-567')
// Snake
expect(toKebeb('path_route')).toEqual('path-route')
expect(toKebeb('PATH_ROUTE')).toEqual('path-route')
expect(toKebeb('path_route0')).toEqual('path-route-0')
expect(toKebeb('path_route_0')).toEqual('path-route-0')
expect(toKebeb('123_path_4_route_567')).toEqual('123-path-4-route-567')
expect(toKebeb('123_path_4_route_567')).toEqual('123-path-4-route-567')
// Camel
expect(toKebeb('pathRoute')).toEqual('path-route')
expect(toKebeb('pathROUTE')).toEqual('path-route')
expect(toKebeb('pathRoute0')).toEqual('path-route-0')
expect(toKebeb('pathROUTE0')).toEqual('path-route-0')
expect(toKebeb('123path4Route567')).toEqual('123-path-4-route-567')
expect(toKebeb('123path4ROUTE567')).toEqual('123-path-4-route-567')
expect(toKebeb('pathRouteA')).toEqual('path-route-a')
expect(toKebeb('pathRouteABC')).toEqual('path-route-abc')
expect(toKebeb('pathIsARoute')).toEqual('path-is-a-route')
// Other
expect(toKebeb('path-route0')).toEqual('path-route-0')
expect(toKebeb('path-route123')).toEqual('path-route-123')
expect(toKebeb('path1route')).toEqual('path-1-route')
expect(toKebeb('path123route')).toEqual('path-123-route')
expect(toKebeb('123pathRoute')).toEqual('123-path-route')
expect(toKebeb('123PATHRoute')).toEqual('123-path-route')
expect(toKebeb('123pathROUTE')).toEqual('123-path-route')
我提到此函数可以转换 几乎 任何字符串,这是因为每个用例处理数字的方式可能不同。例如,期望 3dPrinter
到 return 3d-printer
是完全合理的。可以调整正则表达式来支持这一点,但它会引发其他问题,例如如何处理 3dPrinter12
、my3dPrinter
或 se7en
(即遵守哪些数字-字符串顺序组合)。支持此类规则将大大增加所需的测试数量,并且总会有例外。
为了支持 3dPrinter
示例,您可以将 [0-9]{1,}[a-z]{1,}(?=[A-Z]+)|
添加到正则表达式的开头(在“/”之后),但这会破坏一些早期的规则。
要了解此正则表达式的工作原理,请查看 regexr 上的模式。
function hyphenate(str) {
var replace = "-";
str = str.toLowerCase().replace(/[\s_\b]/g, replace);
console.log(str);
return str;
}
hyphenate("This Is Hyphenate"); // this-is-hyphenate
hyphenate("camelCaseString"); // camel-case-string
我正在尝试让我的代码生成第二个函数调用的结果,但尚未确定可以执行此操作的模式。如有任何帮助,我们将不胜感激。
在小写前尝试先行:
function hyphenate(str) {
return str.split(/[\s_\b]|(?=[A-Z])/).join('-').toLowerCase();
}
您可以使用捕获组获取小写字母后接大写字母,然后将整个字符串转换为小写字母:
str.replace(/([a-z])([A-Z])/g,"-").toLowerCase();
请注意,[\s_\b]
中的 \b
表示退格符。不确定您是否真的需要这个。
使用 ECMAScript 2018 中引入的后视功能更新了答案:
const re = /[\W_]+|(?<=[a-z0-9])(?=[A-Z])/g;
const strs = ['camelCaseString','This Is Hyphenate','This_Should_Hyphenate', '09Report'];
strs.forEach(str =>
console.log( str.replace(re, "-").toLowerCase() )
);
[\W_]+|(?<=[a-z0-9])(?=[A-Z])
正则表达式将匹配
[\W_]+
- 任何 1+ 个非单词和_
个字符|
- 或(?<=[a-z0-9])(?=[A-Z])
- 小写 ASCII letter/digit 和大写 ASCII 字母之间的位置。
旧答案
我会使用有点不同的逻辑:在单词中的每个大写字母前添加一个连字符,然后替换并转为小写:
var re = /[\s_]+|([a-z0-9])(?=[A-Z])/g;
var str = 'camelCaseString<br/>This Is Hyphenate<br/>This_Should_Hyphenate';
var result = str.replace(re, "-").toLowerCase();
document.body.innerHTML += result;
解释:
[\s_]+
- 一个或多个空格或下划线|
- 或者...([a-z0-9])
-(第 1 组)小写字母或数字(因为\B
不允许我们在_
之后匹配大写字母,如果您添加A-Z
想在每个大写字母前添加-
)(?=[A-Z])
- 对大写 ASCII 字母的测试(未使用,因为它(?=[A-Z])
是先行,零宽度断言)。
这可能对您的要求有点矫枉过正,但希望这个答案能帮助任何试图将(几乎)任何字符串转换为烤肉串大小写的人:
const convertStringToKebebCase = str => str && str
.match(/[0-9]{1,}(?=\b)|[A-Z]{2,}(?=[A-Z][a-z]+|[0-9]|\b|_)|[A-Z]?[a-z]+|[A-Z]|[0-9]+/g)
.map(x => x.toLowerCase())
.join('-')
以下是上述函数的测试,因此您可以了解它的行为方式(我将函数重命名为 toKebeb
只是为了在此处更容易阅读):
// Lowercase
expect(toKebeb('path')).toEqual('path')
expect(toKebeb('PATH')).toEqual('path')
// Spaces
expect(toKebeb('path route')).toEqual('path-route')
expect(toKebeb('path route 0')).toEqual('path-route-0')
expect(toKebeb('123 path 4 route 567')).toEqual('123-path-4-route-567')
// Kebab
expect(toKebeb('path-route')).toEqual('path-route')
expect(toKebeb('PATH-ROUTE')).toEqual('path-route')
expect(toKebeb('path-route0')).toEqual('path-route-0')
expect(toKebeb('path-route-0')).toEqual('path-route-0')
expect(toKebeb('123-path-4-route-567')).toEqual('123-path-4-route-567')
expect(toKebeb('123-path-4-route-567')).toEqual('123-path-4-route-567')
// Snake
expect(toKebeb('path_route')).toEqual('path-route')
expect(toKebeb('PATH_ROUTE')).toEqual('path-route')
expect(toKebeb('path_route0')).toEqual('path-route-0')
expect(toKebeb('path_route_0')).toEqual('path-route-0')
expect(toKebeb('123_path_4_route_567')).toEqual('123-path-4-route-567')
expect(toKebeb('123_path_4_route_567')).toEqual('123-path-4-route-567')
// Camel
expect(toKebeb('pathRoute')).toEqual('path-route')
expect(toKebeb('pathROUTE')).toEqual('path-route')
expect(toKebeb('pathRoute0')).toEqual('path-route-0')
expect(toKebeb('pathROUTE0')).toEqual('path-route-0')
expect(toKebeb('123path4Route567')).toEqual('123-path-4-route-567')
expect(toKebeb('123path4ROUTE567')).toEqual('123-path-4-route-567')
expect(toKebeb('pathRouteA')).toEqual('path-route-a')
expect(toKebeb('pathRouteABC')).toEqual('path-route-abc')
expect(toKebeb('pathIsARoute')).toEqual('path-is-a-route')
// Other
expect(toKebeb('path-route0')).toEqual('path-route-0')
expect(toKebeb('path-route123')).toEqual('path-route-123')
expect(toKebeb('path1route')).toEqual('path-1-route')
expect(toKebeb('path123route')).toEqual('path-123-route')
expect(toKebeb('123pathRoute')).toEqual('123-path-route')
expect(toKebeb('123PATHRoute')).toEqual('123-path-route')
expect(toKebeb('123pathROUTE')).toEqual('123-path-route')
我提到此函数可以转换 几乎 任何字符串,这是因为每个用例处理数字的方式可能不同。例如,期望 3dPrinter
到 return 3d-printer
是完全合理的。可以调整正则表达式来支持这一点,但它会引发其他问题,例如如何处理 3dPrinter12
、my3dPrinter
或 se7en
(即遵守哪些数字-字符串顺序组合)。支持此类规则将大大增加所需的测试数量,并且总会有例外。
为了支持 3dPrinter
示例,您可以将 [0-9]{1,}[a-z]{1,}(?=[A-Z]+)|
添加到正则表达式的开头(在“/”之后),但这会破坏一些早期的规则。
要了解此正则表达式的工作原理,请查看 regexr 上的模式。