我想将全逗号分隔的字符串文字转换为双引号,如下所示:
"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']"
...
我的目标字符串都没有跨越多行。
试试这个
:%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
它们都适用于一行中的所有引用字段。