在字母数字字符之间以分号分隔

Posted

技术标签:

【中文标题】在字母数字字符之间以分号分隔【英文标题】:Split on semicolon in between alphanumeric characters 【发布时间】:2018-01-16 05:02:24 【问题描述】:

假设我们有这些字符串:

1. "a;b;c;d;e"
2. "1;2;3;4;5"
3. "!@#$%^&*()_+;!@#$%^&*()_+;"

有没有办法在调用.split(';') 时只在; 在字母数字字符之间时拆分?

预期结果:

1. a, b, c, d, e
2. 1, 2, 3, 4, 5
3. !@#$%^&*()_+;!@#$%^&*()_+; // kept as is

这是我目前所拥有的,但在我“期望”它工作的地方并没有完全正确地分开。

.split(/[A-Za-z0-9];[A-Za-z0-9]/g);

当前结果:

1. (3) ["", ";", ";e"] // no
2. (3) ["", ";", ";5"] // no
3. ["!@#$%^&*()_+;!@#$%^&*()_+;"] // yes

只是为了更新。这不是字符串数组。以上字符串只是示例。还要澄清我期望发生的事情。

分号前面必须有数字或字母。

Yes - both characters beside the ; must be a letter or a number
a;b > a, b
1;2 > 1, 2
c;3 > c, 3
4;d > 4, d
5;6;a; > 5, 6, a 

No - when either of the characters beside the ; is not a letter or a number
!;@
12$;525
aa;!$242
bbbbbb;

另一个更新anubhava 的answer 就像一个魅力,但我在这个特定的字符串中遇到了一些问题。

TestTEST!@#$%^&*()_+|\":?><,./;'[]\\=-this is a long text.test 123455899949949494949499499;TestTEST!@#$%^&*()_+|\":?><,./‌​;'[]\\=-this is a long text.test 123455899949949494949499499

他的回答是/([A-Za-z0-9]+);(?=[A-Za-z0-9])/。但是对上面的字符串使用上述正则表达式会导致

(3) 
"TestTEST!@#$%^&*()_+|":?><,./;'[]\=-this is a long text.test ",
"123455899949949494949499499",
"TestTEST!@#$%^&*()_+|":?><,./;'[]\=-this is a long text.test 123455899949949494949499499"

当预期是

"TestTEST!@#$%^&*()_+|\":?><,./;'[]\\=-this is a long text.test 123455899949949494949499499"
"TestTEST!@#$%^&*()_+|\":?><,./‌​;'[]\\=-this is a long text.test 123455899949949494949499499"

【问题讨论】:

alphanumeric 字符串是哪一个 alphanumeric 表示数字或字母,对吗?所以项目 1 和 2 alphanumeric 根据谷歌是 consisting of or using both letters and numerals. ,但我在这里看不到任何这样的字符串,它有字母或数字 只需使用 for 循环,我现在正在写答案。实际上,不,我不是,hafiz 的答案是完美的,使用正则表达式 我从小就将一个字符称为alphanumeric,无论是字母还是数字。喜欢这个guy。我希望我的例子很清楚。 【参考方案1】:

您可以使用正负lookaheads 来确保分号前后是您想要的字符。因此,这将起作用:

let t1 = "a;b;c;d;e";
let t2 = "1;2;3;4;5";
let t3 = "!@#$%^&*()_+;!@#$%^&*()_+;";

console.log(t1.split(/(?![A-Za-z0-9]);(?=[A-Za-z0-9])/g)); // a, b, c, d, e
console.log(t2.split(/(?![A-Za-z0-9]);(?=[A-Za-z0-9])/g)); // 1, 2, 3, 4, 5
console.log(t3.split(/(?![A-Za-z0-9]);(?=[A-Za-z0-9])/g)); // !@#$%^&*()_+;!@#$%^&*()_+;

目前,您的正则表达式匹配一个字母数字字符,后跟一个分号和另一个字母数字字符。

【讨论】:

(?![A-Za-z0-9]) 在这里没有意义,因为下一个字符无论如何都是分号(即非字母数字)。这也会将#;1 拆分为#, 1,尽管根据问题它不应该拆分。 正如@anubhava 所说,当; 仅被1 个字母数字包围时,它将拆分。两者都必须是字母数字才能拆分。 我在我的问题中添加了更多细节【参考方案2】:

您会看到我在第一个数组中使用了一个“#”作为要测试的垃圾字符,但应该适用于任何非字母数字字符。我假设您的 cmets 您希望消除所有超过 1 个字符的字母数字字符串,所以这就是我尝试做的。

var strs = ["a;bbbb;c;dd;#","1;2;33;4;5","!@#$%^&*()_+;!@#$%^&*()_+;"]

    for (var i = 0; i < strs.length; i++) 
      var str = strs[i].split(';');
      for (var j=0; j < str.length; j++) 
       var chars = str[j];
         if (chars.match(/[^A-Za-z\d]2/g)) 
          console.log('this is our special character string '+strs[i]);
          break;
        
       
       if (chars.length > 1 ) continue;
       var output = chars.split(/[^\s]([a-zA-Z\d]1)/);
        for (var e = 0; e < output.length; e++) 
        var value = output[e];

        if (value && value.match(/[A-Za-z\d]/g)) 
             console.log(value); 
                 
      
     
    

【讨论】:

到目前为止这似乎很有希望,我现在会尝试更多的组合。 12323; 变为 (3) ["123", "3", ""] 12323;! 变为 (3) ["123", "3", "!"] 这感觉真的很hacky,但你可以看看上面我编辑的东西似乎确实有效,尽管你必须重建你的数组而不是简单地拆分。【参考方案3】:

它出现在现代浏览器中 javascript 已经开始支持lookbehind。

如果是这种情况,那么您的解决方案是一个简单的前瞻和后瞻正则表达式,如下所示:

/(?<=[a-z0-9]);(?=[a-z0-9])/i
(?&lt;=[a-z0-9]): 断言我们在前面的位置有一个字母数字 (?=[a-z0-9]): 断言我们在下一个位置有一个字母数字

var inputs = [`TestTEST!@#$%^&*()_+|\":?><,./;'[]\\=-this is a long text.test 123455899949949494949499488;TestTEST!@#$%^&*()_+|\":?><,.;'[]\\=-this is a long text.test 123455899949949494949499499`,
    'a1;b2;c3;d4;e5;', '#;1', 'a;b;c;d;e', '1;2;3;4;5',
    '!@#\$%^&*()_+;!@#\$%^&*()_+;']
    
const re = /(?<=[a-z0-9]);(?=[a-z0-9])/i;

for (var i=0; i<inputs.length; i++)
   console.log(inputs[i].split(re))

然而,在较旧的浏览器中,Javascript 不支持后视。您可以使用捕获组而不是lookbehind 来捕获必须是字母数字的前一个字符,并使用正向lookahead 来断言分号后跟字母数字字符。

你可以使用:

var arr = str.split(/(.*?[a-z0-9]+);(?=[a-z0-9])/i).filter(Boolean)

代码演示:

var inputs = [`TestTEST!@#$%^&*()_+|\":?><,./;'[]\\=-this is a long text.test 123455899949949494949499488;TestTEST!@#$%^&*()_+|\":?><,.;'[]\\=-this is a long text.test 123455899949949494949499499`,
    'a1;b2;c3;d4;e5;', '#;1', 'a;b;c;d;e', '1;2;3;4;5',
    '!@#\$%^&*()_+;!@#\$%^&*()_+;']

var re = /(.*?[a-z0-9]+);(?=[a-z0-9])/i;

for (var i=0; i<inputs.length; i++)
   console.log(inputs[i].split(re).filter(Boolean));

使用filter(Boolean) 过滤掉输出数组中的空结果。

【讨论】:

A1;B2;C3;D4;E5; 变为 (9) ["A", "1", "B", "2", "C", "3", "D", "4", "E5;"] 我刚刚偶然发现了一个问题。 TestTEST!@#$%^&amp;*()_+|\":?&gt;&lt;,./;'[]\\=-this is a long text.test 123455899949949494949499499;TestTEST!@#$%^&amp;*()_+|\":?&gt;&lt;,./;'[]\\=-this is a long text.test 123455899949949494949499499 变为 (3) ["TestTEST!@#$%^&amp;*()_+|":?&gt;&lt;,./;'[]\=-this is a long text.test ", "123455899949949494949499499", "TestTEST!@#$%^&amp;*()_+|":?&gt;&lt;,./;'[]\=-this is a long text.test 123455899949949494949499499"] 上面的字符串应该只是分成2个元素。 更新了我的问题。 我现在在外面。我会在 2 小时内更新它。

以上是关于在字母数字字符之间以分号分隔的主要内容,如果未能解决你的问题,请参考以下文章

从包含以逗号分隔的数字的字符串创建列表;蟒蛇 3

JavaScript03-基本概念一

js 正则获取匹配部分最后一个内容

如何选择从串口接收的号码

15、pandas的设置数字格式,小数位数、百分号、千位分隔符

自定义数字格式字符串始终显示符号