提问者:小点点

如何在Vim中将逗号分隔的字符串转换为Cassandra列表格式?


我想将全逗号分隔的字符串文字转换为双引号,如下所示:

"hello,world,stack,overflow"

转换为Cassandra列表格式:

"['hello','world','stack','overflow']"

其中每个元素都包含在

在我的输入中,这种以逗号分隔的字符串是CSV格式表中行的一部分。下面是一个例子:

other,fields,123,456,"hello,world,stack,overflow"
second,row,567,890,"another,comma,separated,string"
...

我想把它变成:

other,fields,123,456,"['hello','world','stack','overflow']"
second,row,567,890,"['another','comma','separated','string']"
...

我的目标字符串都没有跨越多行。


共2个答案

匿名用户

试试这个

:%s/\v(".*)@<=\s*([^,"]+)\s*(.*")@=/'\2'/g
:%s/"/"[
:%s/"\[\@!/]"

或者一次完成

:%s/\v(".*)@<=\s*([^,"]+)\s*(.*")@=/'\2'/ge | %s/"/"[/e | %s/"\[\@!/]"

这适用于示例。如果行上有多对引号,则不起作用。

解释

:%s/\v(".*)@<=\s*([^,"]+)\s*(.*")@=/'\2'/g

这将查找一个字符串,它的前后都有一个带有lookahead和lookbehinds的引号。然后我们捕获所有不是逗号或引号的内容,并将其替换为单引号中捕获的部分。这会抛出任何前导或尾随空格。

:%s/"/"[

如果您以前使用过: s,这应该是不言自明的

:%s/"\[\@!/]"

这使用负前瞻来查找第一个没有跟随左括号的引号,并用右括号和引号替换它。

在对此进行了更多的思考之后,我认为无论天气如何,您都可以一次完成整个文件,线上有不止一对引号。

第一个函数只是一个帮助函数,它使替代命令更容易输入。(你可以在一行中完成三个替代命令,但那会很难看)。它做的事情与上面的东西相同。

function! ReplaceCommaSeperated(string)
    let l:tmp = substitute(a:string, '[^,"]\+', "'\\0'", 'g')
    let l:tmp = substitute(l:tmp, '"', '"[', '')
    return substitute(l:tmp, '"\[\@!', ']"', '')
endfunction

function! RunCommaReplace()
    %s/".\{-}"/\=ReplaceCommaSeperated(submatch(0))/g 
endfunction

第二个函数找到所有带引号的字符串并将其传递给函数,它会立即被替换。您知道哪一个是开始引号和结束引号,因为保证只有一对引号。

这样做的原因是模式匹配在第一个匹配结束后开始。所以如果你有字符串"A"B"C"
"A"将是第一个匹配,"C"将是第二个匹配,因为当解析器试图在B之后匹配时,它会看到B"C"并且不匹配。

要在您的vim中运行它,只需将这两个函数复制到您的vimrc中。在要运行此文件的文件中运行以下命令。

:call RunCommaReplace()

匿名用户

1.

:%s/"\([^"]*\)"/\='"['.Q.']"'/g

根据上面的命令,所有用双引号括起来的零个或多个字符的序列都将替换为在

表达式的两个版本

2.

>

  • 使用逗号作为分隔符将匹配的文本分解为元素列表:

    split(submatch(1), ',', 1)
    

    (最后一个参数在这里是可选的,只有在双引号字段的开头或结尾可能出现空元素时才需要。)

    用引号包围它们:

    map(‹…›, '"''".v:val."''"')
    

    并按顺序将它们连接起来,与分隔逗号交替:

    join(‹…›, ',')
    

    结合这些步骤,我们得到表达式

    join(map(split(submatch(1), ',', 1), '"''".v:val."''"'), ',')
    

    3.

    的表达

    substitute(submatch(1), '[^,]\+', "'&'", 'g')
    

    导致所有不包含逗号的非空字符序列出现,并在两端附加单引号更改为它们自己。

    如果我们希望这个表达式也处理空列表项(就像上面的第一个变体一样),我们需要做的就是将最后一个模式更改为

    '\%(^\|,\)\zs[^,]*'
    

    这样,它也允许空序列,但受它们位于逗号开头或后面的限制。(请参阅: help\zs:help\%(以更好地了解更改后的模式是如何工作的。)

    4.

    :%s/"\([^"]*\)"/\='"['.join(map(split(submatch(1),',',1),'"''".v:val."''"'),',').']"'/g
    

    :%s/"\([^"]*\)"/\='"['.substitute(submatch(1),'\%(^\|,\)\zs[^,]*',"'&'",'g').']"'/g
    

    它们都适用于一行中的所有引用字段。