regex 正则表达式选择引号对之外的字符

omhiaaxx  于 2023-08-08  发布在  其他
关注(0)|答案(6)|浏览(132)

我想找一个正则表达式,它可以挑出所有落在引号集之外的逗号。
举例来说:

'foo' => 'bar',
'foofoo' => 'bar,bar'

字符串
这将挑出第1行'bar',之后的单个逗号
我真的不在乎单引号和双引号。
有人有什么想法吗?我觉得这应该是可能的readaheads,但我的regex fu太弱。

thigvfpy

thigvfpy1#

这将匹配任何字符串,直到并包括第一个非引号“,”。这就是你想要的吗

/^([^"]|"[^"]*")*?(,)/

字符串
如果你想要所有这些(作为一个反例,那个说这不可能的人),你可以写:

/(,)(?=(?:[^"]|"[^"]*")*$)/


这将匹配所有这些。因此

'test, a "comma,", bob, ",sam,",here'.gsub(/(,)(?=(?:[^"]|"[^"]*")*$)/,';')


用分号替换引号内的所有逗号 not,并生成:

'test; a "comma,"; bob; ",sam,";here'


如果你需要它跨换行符工作,只需添加m(多行)标志。

lg40wkob

lg40wkob2#

下面的正则表达式将匹配双引号外的所有逗号,

,(?=(?:[^"]*"[^"]*")*[^"]*$)

字符串
DEMO

(仅PCRE)

"[^"]*"(*SKIP)(*F)|,


"[^"]*"匹配所有双引号块。也就是说,在这个buz,"bar,foo"输入中,这个正则表达式将只匹配"bar,foo"。现在下面的(*SKIP)(*F)使匹配失败。然后,它移动到|符号旁边的模式,并尝试匹配剩余字符串中的字符。也就是说,在我们的输出中,|旁边的,将只匹配buz后面的逗号。请注意,这不会匹配双引号内的逗号,因为我们已经跳过了双引号部分。
DEMO
下面的正则表达式将匹配双引号内的所有逗号,

,(?!(?:[^"]*"[^"]*")*[^"]*$)


DEMO

g2ieeal7

g2ieeal73#

虽然可以使用正则表达式(我和其他人一样喜欢滥用正则表达式),但如果没有更高级的解析器来处理子字符串,您迟早会遇到麻烦。可能的麻烦包括混合引号和转义引号。
此函数将按逗号拆分字符串,但不拆分单引号或双引号字符串中的逗号。它可以很容易地扩展额外的字符作为引号(尽管像« »这样的字符对需要多几行代码),甚至会告诉你是否忘记关闭数据中的引号:

function splitNotStrings(str){
  var parse=[], inString=false, escape=0, end=0

  for(var i=0, c; c=str[i]; i++){ // looping over the characters in str
    if(c==='\\'){ escape^=1; continue} // 1 when odd number of consecutive \
    if(c===','){
      if(!inString){
        parse.push(str.slice(end, i))
        end=i+1
      }
    }
    else if(splitNotStrings.quotes.indexOf(c)>-1 && !escape){
      if(c===inString) inString=false
      else if(!inString) inString=c
    }
    escape=0
  }
  // now we finished parsing, strings should be closed
  if(inString) throw SyntaxError('expected matching '+inString)
  if(end<i) parse.push(str.slice(end, i))
  return parse
}

splitNotStrings.quotes="'\"" // add other (symmetrical) quotes here

字符串

bfhwhh0e

bfhwhh0e4#

试试这个正则表达式:

(?:"(?:[^\\"]+|\\(?:\\\\)*[\\"])*"|'(?:[^\\']+|\\(?:\\\\)*[\\'])*')\s*=>\s*(?:"(?:[^\\"]+|\\(?:\\\\)*[\\"])*"|'(?:[^\\']+|\\(?:\\\\)*[\\'])*')\s*,

字符串
这也允许像“'foo\'bar' => 'bar\\',”这样的字符串。

56lgkhnf

56lgkhnf5#

MarkusQ的回答对我来说很有效,大约一年,直到它没有。我刚刚得到一个堆栈溢出错误,一行大约有120个逗号和3682个字符。在Java中,像这样:

String[] cells = line.split("[\t,](?=(?:[^\"]|\"[^\"]*\")*$)", -1);

字符串
下面是我的非常不优雅的替代品,它不会堆栈溢出:

private String[] extractCellsFromLine(String line) {
    List<String> cellList = new ArrayList<String>();
    while (true) {
        String[] firstCellAndRest;
        if (line.startsWith("\"")) {
            firstCellAndRest = line.split("([\t,])(?=(?:[^\"]|\"[^\"]*\")*$)", 2);
        }
        else {
            firstCellAndRest = line.split("[\t,]", 2);                
        }
        cellList.add(firstCellAndRest[0]);
        if (firstCellAndRest.length == 1) {
            break;
        }
        line = firstCellAndRest[1];
    }
    return cellList.toArray(new String[cellList.size()]);
}

baubqpgj

baubqpgj6#

@SocialCensus,您在MarkusQ的评论中给出的示例(其中您添加了“与......并排“)与MarkusQ在上面给出的示例不兼容,如果我们将 sam 更改为 sam's :(test,a“逗号,",bob,“,sam's,",此处)与(,)(?=(?:[^"']|[”|'][^"']”)$).事实上,这个问题本身,“我并不真正关心单引号和双引号”,是模棱两可的。你必须弄清楚你用“或"来引用是什么意思。例如,是否允许嵌套?若有,有几个层次?如果只有1个嵌套级别,则内部嵌套引号之外但外部嵌套引号之内的逗号会发生什么情况?你还应该考虑到单引号本身是作为撇号出现的(例如,就像我前面用sam's给出的反例)。最后,您所创建的正则表达式并没有真正将单引号与双引号等同对待,因为它假定最后一种引号必须是双引号--并将最后一个双引号替换为['|“]也有一个问题,如果文本没有正确的引号(或如果使用了撇号),虽然,我想我们可能可以假设所有的引号都是正确的划定。
MarkusQ的正则表达式回答了这个问题:找出所有后面有偶数个双引号的逗号(即在双引号外),并忽略所有后面有奇数个双引号的逗号(即在双引号内)。这通常与您可能需要的解决方案相同,但让我们来看看一些异常情况。首先,如果有人在结尾处留下了引号,那么这个正则表达式会找到所有错误的逗号,而不是找到所需的逗号或无法匹配任何逗号。当然,如果一个双引号丢失了,所有的赌注都没有了,因为可能不清楚丢失的双引号是属于结尾还是属于开头;然而,有一种情况是合法的,其中正则表达式可能会失败(这是第二个“异常”)。如果您调整正则表达式使其跨越文本行,则应注意,引用多个连续段落需要在每个段落的开头放置一个单双引号,并省略每个段落末尾的引号(最后一个段落末尾的引号除外)。这意味着在这些段落的空间上,正则表达式在某些地方失败,而在另一些地方成功。
段落引用和嵌套引用的示例和简要讨论可以在http://en.wikipedia.org/wiki/Quotation_mark中找到。

相关问题