如何使用自定义正则表达式拆分字符串?

How can I split string using custom regex?

提问人: 提问时间:6/13/2023 最后编辑:Peter Seliger 更新时间:6/26/2023 访问量:128

问:

let myString = "Hello 'How are you' foo bar abc 'Strings are cool' d b s ;12gh gh76;"

const myRegEx = / \w+ "\w* +" | ;\w +; +/g  // This what i have figured but its not working :(

const splitedString = myString.split(myRegEx)

console.log(splitedString)

预期输出:

["Hello", "How are you", "foo", "bar", abc, "Strings are cool", "d", "b", "s", "12gh-gh76"]

让我试着解释更多:

首先,所有基于空格 “ ” 拆分整个字符串,除了 里面的字符串 或 ,如:'';;

"Hello 'Yo what's up'" --> ["Hello", "Yo-what's-up"](注意:这里是额外的内容,所以也要处理它。''

然后,如果字符串在里面,那么concat(我相信这是正确的名称)它,就像:;;-Hello ;hi there; --> ["Hello", "hi-there"]

最后返回一个包含所有格式化的数组......作为预期的输出。

JavaScript 正则表达式 字符串 替换 匹配

评论

1赞 markalex 6/13/2023
像 和 这样的短语应该会发生什么?'a ;b c; d';a 'b c' d;
0赞 6/13/2023
哦,从来没想过,我需要的只是在空格的基础上拆分整个字符串,而不是拆分里面的单词和里面的单词,因为字符串将永远是我提供的这种格式。几个例子:希望这对您有所帮助......'';;-"Hey 'hwy hi bye' ;lol 123; ""Wow ;what a great catch; 'yay that was funny' 'ooh that's realy bad' 'oh my god'""Realy 'you wanna do that?' ;no i don't; ;yes you do; 'I said, no!'"
0赞 markalex 6/13/2023
您可以使用以下正则表达式代替拆分:([';])。+?\1|\w+,然后遍历结果,删除换行引号,并更改为 interdependently。matchAll;a b;a-b
0赞 6/13/2023
@markalex 你能不能看看这个片段,并告诉它在哪里是一个好方法,如果不是,你能帮忙省略它吗,我无法转换,请看看那部分也......;abc def; -> abc-def

答:

1赞 markalex 6/13/2023 #1

您可以使用而不是拆分来查找引号、分号对或使用正则表达式 ([';]) 分隔的单词的匹配内容。+?\1|\w+.matchAll

然后取下包装并在需要的地方替换空格。

const myRegEx = new RegExp(/([';]).+?\1|\w+/gm)

const message = "Hello 'How are you' foo bar abc 'Strings are cool' d b s ;12gh gh76; ;a 'b c' d; 'a ;b c; d' d" // Try edit me

const matches = Array.from(message.matchAll(myRegEx))

const finalResult = matches.map(str => {
  const value = str.shift()
  if(value.match(/^;.*;$/))
    return value.substring(1, value.length-1).replaceAll(' ', '-')
  else if(value.match(/^'.*'$/))
    return value.substring(1, value.length-1)
  else
    return value
})

// Log to console
console.log(finalResult)

请注意,此解决方案的工作原理是假设包装器(引号和分号)未嵌套。

如果你需要考虑嵌套包装器,正则表达式不是这项工作的最佳工具,因为你需要检查“括号”-平衡,虽然使用正则表达式是可能的,但更简单的方法可以做到这一点。

评论

0赞 6/14/2023
非常感谢你,但是输出数组中的最后一秒字符串没有格式化,我的需求不是那么多,而只是出于好奇a ;b c; d --> a b-c d
0赞 markalex 6/14/2023
@AkT01,正如我在回答中指出的那样,“嵌套”并不是一件容易的事。(另外,您在评论中表示这不会发生)。我相信最好的通用解决方案是将生成的字符串拆分为 ,将空格替换为每个偶数索引元素中的空格,然后重新连接它。;-
0赞 InSync 6/14/2023
@markalex 你是说奇数索引? 第二个元素的索引为 1。b c
0赞 markalex 6/14/2023
@InSync,是的,当然。可能不好。
0赞 6/14/2023
@markalex是的,我没有读过,我的错,但我想在我的场景中告诉大家,这两种情况永远不需要处理:-0'abc ; def ghi; jkl';a 'b c' d;
1赞 The fourth bird 6/13/2023 #2

您可以捕获要重新格式化的部件,然后在处理它们后检查捕获组编号:

'([^']+(?:'[^\s'][^']*)*)'|;([^;]+);|\S+

模式匹配:

  • '火柴'
  • (捕获组 1
    • [^']+'匹配 1+ 个字符,后跟''
    • (?:'[^\s'][^']*)*(可选)重复单个非空格字符,后跟可选字符,而不是''
  • )关闭组
  • '火柴'
  • |
  • ;([^;]+);组 2 中匹配并捕获内部内容;...;
  • |
  • \S+匹配 1+ whitspace 字符

正则表达式演示

const regex = /'([^']+(?:'[^\s'][^']*)*)'|;([^;]+);|\S+/g;
const s = `Hello  'Yo what's up'`;
[
  `Hello 'Yo what's up'`,
  `Hello 'How are you' foo bar abc 'Strings are cool' d b s ;12gh gh76;`,
  `Hello ;hi there;`
].forEach(s =>
  console.log(
    Array.from(
      s.matchAll(regex), m => {
        if (m[1]) return m[1]
        else if (m[2]) return m[2].replace(/\s+/g, "-");
        else return m[0];
      }
    )
  )
);

评论

0赞 6/13/2023
里面的单词不应该与 .但是很好的回答,非常感谢:)''-
0赞 The fourth bird 6/14/2023
@AkT01 哦,是的,让我改变一下。
0赞 6/14/2023
解释也很好,但对不起,我已经接受了其他人的答案,因为他是第一个发表评论的人,两个答案都很好,他还修改了我提供的功能,老实说,我很困惑要接受什么,所以最终我选择了那个家伙的答案,但你做得很好, 希望您能理解,非常感谢:)
0赞 The fourth bird 6/14/2023
@AkT01 你做的是对的,不用担心!:-)
2赞 Peter Seliger 6/14/2023 #3

人们至少需要两种折叠的方法

首先,必须通过用单个破折号替换其每个空格序列来替换任何分号分隔的范围,这看起来像......

`Hello 'how\\'re you feeling' foo bar abc 'Strings are cool' d b s ;12gh gh76;`
  .replace(/;([^;]*);/g, (match, capture) => capture.replace(/\s+/g, '-'))

...正则表达式在哪里....../;([^;]*);/g ...结果将是......

"Hello 'how\\'re you feeling' foo bar abc 'Strings are cool' d b s 12gh-gh76"

其次,需要想出一个可以同时处理两者的拆分正则表达式,在任何空格(序列)处拆分,但前提是它不是单引号封闭子字符串的一部分。后者需要被捕获才能在分裂时保存。然后,上面的示例代码继续看起来像...

`Hello 'how\\'re you feeling' foo bar abc 'Strings are cool' d b s ;12gh gh76;`
  .replace(/;([^;]*);/g, (match, capture) => capture.replace(/\s+/g, '-'))
  .split(/'(.*?(?<!\\))'|\s+/)

...其中,拆分正则表达式是....../'(.*?(?<!\\))'|\s+/ ...生成的数组确实包含大量空值,例如字符串值和未定义值。因此,该任务需要伴随着一个基于reduce的清理任务......split

`Hello 'how\\'re you feeling' foo bar abc 'Strings are cool' d b s ;12gh gh76;`
  .replace(/;([^;]*);/g, (match, capture) => capture.replace(/\s+/g, '-'))
  .split(/'(.*?(?<!\\))'|\s+/)
  .reduce((result, item) => item && result.concat(item) || result, [])

下一个提供的示例代码只是证明了上述方法的解释......

const sampleString =
  `Hello 'how\\'re you feeling' foo bar abc 'Strings are cool' d b s ;12gh gh76;`;

// see ... [https://regex101.com/r/ZShVPL/1]
const regXSplitAlternation = /'(.*?(?<!\\))'|\s+/;

// see ... [https://regex101.com/r/ZShVPL/2]
const regXSemicolonRange = /;([^;]*);/g

console.log(
  sampleString
    // first ... 
    // ... replace any semicolon delimited range by replacing 
    //     each of its whitespace sequence(s) with a single dash.
    .replace(regXSemicolonRange, (match, capture) => capture.replace(/\s+/g, '-'))
);
console.log(
  sampleString
    .replace(regXSemicolonRange, (match, capture) => capture.replace(/\s+/g, '-'))
    // second ...
    // ... split the intermediate replacement string at
    //      - either a single quoted character sequence (capturing it)
    //      - or a whitespace (sequence) (not capturing the latter).
    .split(regXSplitAlternation)
    // ... and third ... do omit any empty (undefined, empty string) item.
    .reduce((result, item) => item && result.concat(item) || result, [])
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

评论

0赞 6/14/2023
对我来说似乎很专业的东西, ;_;我是中级人员,而且我必须尽可能多地理解它,因为我必须将它放入我的打字稿代码中,因为我实际上在我的项目中使用打字稿,我的场景对我来说似乎是 javascript,所以我想我应该把它作为 javascript 问题来问。
0赞 Peter Seliger 6/14/2023
@AkT01......因为这是一个组合的 JavaScript/正则表达式问题,为了全面,并不是说高级方法有可消化的部分,如替换拆分减少,每个都有自己的解释和 JS 文档和正则表达式游乐场链接。