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

gcuhipw9  于 2023-06-05  发布在  Cassandra
关注(0)|答案(2)|浏览(214)

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

"hello,world,stack,overflow"

Cassandra列表格式:

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

其中每个元素都包含在单引号中,整个原始字符串包含在方括号和双引号中。如何在Vim中实现?
在我的输入中,这种用逗号分隔的引用字符串是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']"
...

我的目标字符串没有一个跨多行。

ibrsph3r

ibrsph3r1#

试试这个

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

或者一下子全部

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

这在示例中起作用。如果行中有多对引号,则此操作将不起作用。
说明

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

这将查找前后都有引号的字符串,并使用lookaheads和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()
cbeh67ev

cbeh67ev2#

**1.**很有可能一次运行:substitute命令就能解决问题。我可以看到这种方法的两种稍微不同的实现。它们都遵循相同的表达式替换模式:

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

根据上面的命令,所有包含零个或多个字符的双引号序列都将被\=符号后指定的表达式的计算结果替换(参见:help sub-replace-\=)。要与周围的方括号和引号连接的是替换表达式Q,它代表一个表达式,该表达式将逗号分隔的列表(由模式的(唯一)子匹配捕获)的文本转换为同一列表的字符串,其中项目用单引号括起来。
表达式Q的两个版本如下所示。

**2.**第一个版本很简单:

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

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

(The最后一个参数在这里是可选的,只有当双引号字段的开头或结尾可能有空元素时才是必需的。)
1.用引号包围它们:

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

1.然后将它们按顺序连接起来,用逗号分隔:

join(‹…›, ',')

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

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

**3.**表达式Q的第二个更高性能的版本并不复杂;它只是一个替换(在替换内部,如Q:s命令内部)。我们可以使用substitute()函数,它的功能相当于同名命令。

表达

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

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

相关问题