简体   繁体   English

将驼峰字符串转换为烤肉串的常规 rxpression

[英]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

I am trying to get my code to produce the results of the second function call, but have not identified a pattern that can do this.我试图让我的代码产生第二个函数调用的结果,但还没有确定可以做到这一点的模式。 Any assistance would be greatly appreciated.任何帮助将不胜感激。

Note that \\b in your [\\s_\\b] means a backspace character.需要注意的是\\b[\\s_\\b]表示退格字符。 Not sure you really need this.不确定你真的需要这个。

Updated answer using the lookbehind feature introduced in ECMAScript 2018 :使用 ECMAScript 2018 中引入的后视功能更新了答案

 const re = /[\\W_]+|(?<=[a-z0-9])(?=[AZ])/g; const strs = ['camelCaseString','This Is Hyphenate','This_Should_Hyphenate', '09Report']; strs.forEach(str => console.log( str.replace(re, "-").toLowerCase() ) );

The [\\W_]+|(?<=[a-z0-9])(?=[AZ]) regex will match [\\W_]+|(?<=[a-z0-9])(?=[AZ])正则表达式将匹配

  • [\\W_]+ - any 1+ non-word and _ chars [\\W_]+ - 任何 1+ 个非单词和_字符
  • | - or - 或者
  • (?<=[a-z0-9])(?=[AZ]) - a location between a lowercase ASCII letter/digit and an uppercase ASCII letter. (?<=[a-z0-9])(?=[AZ]) - 小写 ASCII 字母/数字和大写 ASCII 字母之间的位置。

Old answer旧答案

I'd use a bit different logic: add a hyphen before each capital letter inside a word, and then replace and turn lowercase:我会使用一些不同的逻辑:在单词内的每个大写字母前添加一个连字符,然后替换并变成小写:

 var re = /[\\s_]+|([a-z0-9])(?=[AZ])/g; var str = 'camelCaseString<br/>This Is Hyphenate<br/>This_Should_Hyphenate'; var result = str.replace(re, "$1-").toLowerCase(); document.body.innerHTML += result;

Explanation:解释:

  • [\\s_]+ - one or more whitespaces or underscores [\\s_]+ - 一个或多个空格或下划线
  • | - or... - 或者...
  • ([a-z0-9]) - (Group 1) a lowercase letter or digit (since \\B would not let us match an uppercase letter after _ , add AZ if you want to add - before each uppercase letter) ([a-z0-9]) - (第 1 组)小写字母或数字(因为\\B不允许我们在_之后匹配大写字母,如果您想在每个大写字母之前添加- ,请添加AZ
  • (?=[AZ]) - a test for an uppercase ASCII letter (that is not consumed since it (?=[AZ]) is a lookahead, a zero width assertion). (?=[AZ]) - 对大写 ASCII 字母的测试(由于它(?=[AZ])是前瞻,零宽度断言,因此不会被消耗)。

Try a lookahead before lowercasing:在小写之前尝试先行:

function hyphenate(str) {
  return str.split(/[\s_\b]|(?=[A-Z])/).join('-').toLowerCase();
}

您可以使用捕获组来获取小写字母后跟大写字母,然后将整个字符串转换为小写字母:

str.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();

This maybe overkill to your requirements, but hopefully this answer will help anyone who is trying to convert (almost) any string into kebab case:这可能对您的要求有点过分,但希望这个答案能帮助任何试图将(几乎)任何字符串转换为烤肉串的人:

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('-')

Here are the tests for the above function so you can work out how it behaves (I renamed the function to toKebeb just to make it easier to read here):以下是对上述函数的测试,因此您可以了解它的行为(我将函数重命名为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')

I mentioned that this function converts almost any string, and that is because of the way numbers are handled may differ for each use case.我提到这个函数几乎可以转换任何字符串,这是因为每个用例的数字处理方式可能不同。 For example, it would be perfectly reasonable to expect 3dPrinter to return 3d-printer .例如,期望3dPrinter返回3d-printer是完全合理的。 The regex can be tweaked to support this, but it raises other issues such as how to handle 3dPrinter12 , my3dPrinter or se7en (ie which number-string order combinations are respected).可以调整正则表达式以支持这一点,但它会引发其他问题,例如如何处理3dPrinter12my3dPrinterse7en (即,遵守哪些数字-字符串顺序组合)。 Supporting such rules would massively increase the number of tests required and there will always be exceptions.支持此类规则将大量增加所需的测试数量,并且总会有例外。

To support the 3dPrinter example, you could add [0-9]{1,}[az]{1,}(?=[AZ]+)|要支持3dPrinter示例,您可以添加[0-9]{1,}[az]{1,}(?=[AZ]+)| to the start of the regex (after the "/"), but it would break some of the earlier rules.到正则表达式的开头(在“/”之后),但它会破坏一些早期的规则。

To learn about how this regex works, checkout the pattern on regexr .要了解此正则表达式的工作原理,请查看regexr上的模式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM