2

次のように、すべてカンマで区切られた文字列リテラルを二重引用符で囲み、変換したいと考えています。

"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']"
...

複数行にまたがるターゲット文字列はありません。

4

2 に答える 2

6

これを試して

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

または一度に

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

これは例で機能します。行に複数の引用符のペアがある場合、これは機能しません。

説明

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

これは、先読みと後読みを使用して、前後に引用符がある文字列を探します。次に、コンマまたは引用符ではないすべてをキャプチャし、単一引用符で囲まれたキャプチャされた部分に置き換えます。これにより、先頭または末尾のスペースがすべて破棄されます。

:%s/"/"[

:s以前に使用したことがある場合、これは自明のはずです

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

これは、否定先読みを使用して、左括弧が後に続かない最初の引用を見つけ、それを右括弧と引用に置き換えます。


これについてもう少し考えた後、行に複数の引用符のペアがあるかどうかに関係なく、ファイル全体を一度に実行できると思います。

最初の関数は、代替コマンドを入力しやすくする単なるヘルパー関数です。(1 行で 3 つの代替コマンドを実行することもできましたが、それは見苦しかったでしょう)。上記のものと同じことを行います。

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

2 番目の関数は、引用符で囲まれたすべての文字列を見つけて関数に渡し、一度にすべて置き換えます。また、引用符のペアは 1 つだけであることが保証されているため、どちらが開始引用符と終了引用符であるかがわかります。

これが機能し、正規表現パーサーが混乱しない理由は、パターン マッチングが最初の一致の終了後に開始されるためです。したがって、文字列" A " B " C "
" A "が最初に一致し" C "、2 番目に一致する場合は、パーサーが B の後に一致しようとすると、一致B " C "しないことがわかります。

これを vim で実行するには、2 つの関数を vimrc にコピーするだけです。そして、これを実行したいファイルで、次のコマンドを実行します。

:call RunCommaReplace()
于 2013-08-09T23:21:27.663 に答える