Language agnostic 拆分字符串时忽略带引号的部分

Language agnostic 拆分字符串时忽略带引号的部分,language-agnostic,parsing,csv,Language Agnostic,Parsing,Csv,给定如下字符串: a、 “字符串,带”,各种,“值和一些”,引用 在忽略引用部分中的逗号的情况下,什么是一种基于逗号分割的好算法 输出应该是一个数组: [“a”,“string,with”,“variable”,“value,and some”,“quoted”] 当然,使用CSV解析器更好,但为了好玩,您可以: Loop on the string letter by letter. If current_letter == quote : toggle inside

给定如下字符串:

a、 “字符串,带”,各种,“值和一些”,引用

在忽略引用部分中的逗号的情况下,什么是一种基于逗号分割的好算法

输出应该是一个数组:

[“a”,“string,with”,“variable”,“value,and some”,“quoted”]


当然,使用CSV解析器更好,但为了好玩,您可以:

Loop on the string letter by letter.
    If current_letter == quote : 
        toggle inside_quote variable.
    Else if (current_letter ==comma and not inside_quote) : 
        push current_word into array and clear current_word.
    Else 
        append the current_letter to current_word
When the loop is done push the current_word into array 

作者在这里插入了一块C代码,用于处理您遇到问题的场景:


不应该太难翻译。

< P>如果我的选择语言没有提供一种方法而不用思考,那么我会首先考虑两种选择,作为简单的出路:

  • 对字符串进行预分析,并用另一个控制字符替换字符串中的逗号,然后拆分它们,然后对数组进行后分析,以用逗号替换以前使用的控制字符

  • 或者,在逗号上拆分它们,然后将生成的数组后解析为另一个数组,检查每个数组项上的前导引号,并连接这些项,直到到达终止引号为止


  • 然而,这些都是黑客行为,如果这是一个纯粹的“心理”练习,那么我怀疑它们将证明毫无用处。如果这是一个真实的问题,那么了解该语言将有助于我们提供一些具体的建议。

    我用它来解析字符串,不确定它是否有帮助;但也许需要一些小的修改

    function getstringbetween($string, $start, $end){
        $string = " ".$string;
        $ini = strpos($string,$start);
        if ($ini == 0) return "";
        $ini += strlen($start);   
        $len = strpos($string,$end,$ini) - $ini;
        return substr($string,$ini,$len);
    }
    
    $fullstring = "this is my [tag]dog[/tag]";
    $parsed = getstringbetween($fullstring, "[tag]", "[/tag]");
    
    echo $parsed; // (result = dog) 
    

    /mp

    这里有一个简单的算法:

  • 确定字符串是否以“字符开头”
  • 将字符串拆分为一个由“字符分隔的数组
  • 用占位符
    #逗号#
    标记引用的逗号
    • 如果输入以“”开头,请在数组中标记索引%2==0的项目
    • 否则,请标记数组中索引%2==1的项目
  • 连接数组中的项以形成修改后的输入字符串
  • 将字符串拆分为一个数组,该数组由“
    ”和“
    字符分隔
  • #逗号#
    占位符数组中的所有实例替换为
    ,'
    字符
  • 数组是您的输出
  • 下面是python实现:
    (固定为处理“a,b”,c,“d,e,f,h”,“i,j,k”)


    这是一个标准的CSV风格的解析。很多人都尝试用正则表达式来实现这一点。使用正则表达式可以达到90%左右的解析率,但您确实需要一个真正的CSV解析器来正确完成。几个月前我发现了一个我极力推荐的方法!

    这里有一个伪代码(也称为Python)一次性实现:-p
    def parsecsv(instr):
    i=0
    j=0
    超出额=[]
    #我是固定的,直到匹配发生,然后它前进
    #每次通过以下通道向前移动最大j.j英寸:
    而我2且s[0]=''”,且s[-1]=''”:
    s=s[1:-1]
    #将其添加到结果中
    未完成追加
    #跳过逗号,向上移动i(到何处
    #j将在迭代结束时)
    i=j+1
    j=j+1
    回击出局者
    def测试用例(仪表,预期):
    outstr=parsecsv(instr)
    打印输出
    断言应为==outsr
    #不会处理像“1,2”,a,b,c,d,2”或
    #转义引号,但是可以很容易地添加这些引号。
    测试用例('a,b,“1,2,3”,c',['a','b','1,2,3','c'])
    测试用例('a,b,“1,2,3”,c',['a','b','1,2,3','c'])
    #奇数引号表示“不匹配引号”异常
    #测试用例('a,b,“1,2,3”,“c”,“a”,“b”,“1,2,3”,“c']))
    
    看起来您在这里找到了一些不错的答案

    对于那些希望处理自己的CSV文件解析的人,请听取专家和管理员的建议

    您的第一个想法是,“我需要在引号中处理逗号。”

    你的下一个想法是,“哦,废话,我需要处理引号内的引号。转义引号。双引号。单引号…”


    这是一条疯狂之路。不要自己写。找到一个具有广泛单元测试覆盖率的库,该库覆盖了所有困难的部分,并且为您经历了地狱。对于.NET,请使用免费库。

    我忍不住想看看是否可以在Python一行程序中使用它:

    arr = [i.replace("|", ",") for i in re.sub('"([^"]*)\,([^"]*)"',"\g<1>|\g<2>", str_to_test).split(",")]
    
    arr=[i.replace(“;”,“,”)代表re.sub中的i(“([^”]*)\,([^”]*)”,“\g | \g”,stru to_test)。拆分(“,”)
    
    返回['a','string,带','各种','值和一些','引号'] 它首先将“,”内引号替换为另一个分隔符(|),
    在“,”上拆分字符串并再次替换|分隔符。

    Python:

    import csv
    reader = csv.reader(open("some.csv"))
    for row in reader:
        print row
    

    如果出现奇数引号怎么办 在原始字符串中

    这看起来很像CSV解析,它在处理带引号的字段时有一些特殊性。仅当字段用双引号分隔时,才会转义该字段,因此:

    字段1,“字段2,字段3”,字段4,“字段5,字段6”字段7

    变成

    字段1

    场2,场3

    字段4

    “第5场

    字段6“字段7

    请注意,如果它不是以引号开始和结束,那么它就不是一个带引号的字段,双引号被简单地视为双引号

    顺便说一句,如果我没记错的话,我链接到的代码实际上没有正确处理这个问题。

    这里有一个简单的pytho
    arr = [i.replace("|", ",") for i in re.sub('"([^"]*)\,([^"]*)"',"\g<1>|\g<2>", str_to_test).split(",")]
    
    import csv
    reader = csv.reader(open("some.csv"))
    for row in reader:
        print row
    
    def splitIgnoringSingleQuote(string, split_char, remove_quotes=False):
        string_split = []
        current_word = ""
        inside_quote = False
        for letter in string:
          if letter == "'":
            if not remove_quotes:
               current_word += letter
            if inside_quote:
              inside_quote = False
            else:
              inside_quote = True
          elif letter == split_char and not inside_quote:
            string_split.append(current_word)
            current_word = ""
          else:
            current_word += letter
        string_split.append(current_word)
        return string_split
    
    def find_character_indices(s, ch):
        return [i for i, ltr in enumerate(s) if ltr == ch]
    
    
    def split_text_preserving_quotes(content, include_quotes=False):
        quote_indices = find_character_indices(content, '"')
    
        output = content[:quote_indices[0]].split()
    
        for i in range(1, len(quote_indices)):
            if i % 2 == 1: # end of quoted sequence
                start = quote_indices[i - 1]
                end = quote_indices[i] + 1
                output.extend([content[start:end]])
    
            else:
                start = quote_indices[i - 1] + 1
                end = quote_indices[i]
                split_section = content[start:end].split()
                output.extend(split_section)
    
            output += content[quote_indices[-1] + 1:].split()                                                                 
    
        return output