2012-02-08 9 views
3

プロジェクト:Vim regex:上書きされた逆参照?

はCSVにデータを入れ、執政官のWikipediaのリストを取るので、私はconsulageの面で

例データソースを様々な氏族の立ち上がりと立ち下がりのグラフを作ることができます

509,L. Iunius Brutus,L. Tarquinius Collatinus 
suff.,Sp. Lucretius Tricipitinus,P. Valerius Poplicola 
suff.,M. Horatius Pulvillus, 
508,P. Valerius Poplicola II,T. Lucretius Tricipitinus 
507,P. Valerius Poplicola III,M. Horatius Pulvillus II 

Vimの検索:だから、基本的に

/\v(\d+|suff\.),((\w+\.=) (\w+)(\s\w+)=(\s\w+)=(\s[iv]+)=(\s\(.{-}\))=,=){,2} 

  1. 最初(またはsuffect領事の表示)で、年間検索:(\d+|suff\.)
  2. 次のグループは、(のは外側のグループを呼びましょう)2回まで発見される必要があります。これらのそれぞれについて(outer group){,2}
  3. 二つの外側のグループ、見つける:オプションの期間と
    1. プラエノーメン、(時にはこれが存在しない):(\w+.=)
    2. Nomen:すべてそうであるように(\w+)
    3. オプションコグノーメンは(、スペースが含まれ):(\s\w+)=
    4. 任意の年齢:(\s\w+)=
    5. オプションの反復(彼が領事であったn番目の時間を示します)。 "Sicinius(?Sabinus)" のような(\s[iv]+)=
    6. オプション説明文:

    (最終コンマ(\s\(.{-}\))=

は以来、オプションであるデータソースは、8回の以上の反復(私とVは十分です)を持っていませんだから、後方参照があることが判明し、それは、行の終わりです)

:。

\1: year or suffect 
\2: the entire second outer group 
\3: Praenomen of second outer group (same with all below) 
\4: Nomen 
\5: Cognomen 
\6: Agnomen 
\7: Iteration 
\8: Explanatory note 

問題は、私はどのように把握することはできませんです最初の外側のグループをキャプチャします。 \ 2と\ 3- \ 8の参照は、その2番目の外部グループを参照すると上書きされます。これを使用する

は交換してください:

:%s//1:{\1}^I2:{\2}^I3:{\3}^I4:{\4}^I5:{\5}^I6:{\6}^I7:{\7}^I8:{\8}^I9:{\9} 

を、私はこの出力を得る:

1:{509} 2:{L. Tarquinius Collatinus} 3:{L.} 4:{Tarquinius} 5:{ Collatinus} 6:{} 7:{} 8:{} 9:{} 
1:{suff.} 2:{P. Valerius Poplicola} 3:{P.} 4:{Valerius} 5:{ Poplicola} 6:{} 7:{} 8:{} 9:{} 
1:{suff.} 2:{M. Horatius Pulvillus,} 3:{M.} 4:{Horatius} 5:{ Pulvillus} 6:{} 7:{} 8:{} 9:{} 
1:{508} 2:{T. Lucretius Tricipitinus} 3:{T.} 4:{Lucretius} 5:{ Tricipitinus} 6:{ II} 7:{} 8:{} 9:{} 
1:{507} 2:{M. Horatius Pulvillus II} 3:{M.} 4:{Horatius} 5:{ Pulvillus} 6:{ II} 7:{} 8:{} 9:{} 

私が第一の外側グループ内のこれらのグループにアクセスすることはできません。私は彼らが上書きされていると思います:上書きされていますか?もしそうなら、これを回避する方法はありますか?

編集: オリジナルタイトルVimの正規表現(または任意の互換性のある正規表現):外側のグループが繰り返される場合にどのように(グループ内の)グループを参照するために?

+0

がリンク行方不明:http://en.wikipedia.org/wiki/List_of_Roman_consulsは – sehe

答えて

4

私はそれをすべてnormal(しゃれ意図)の方法をやってするのではなく、vimの機能を採用し、サブステップでそれを打破したい:

/\v(.{-}),(.{-}),(.*) 

は、私が何をしたかを参照してください?わずかに少ない怠惰取得編集

それははるかに簡単かつ明確に作られた、のは3つのストリングの最小値に分割し、それらをtabseparateするヘルパー関数を定義してみましょう:

function! Consul(s)   
    return join((split(a:s) + ["","",""])[0:2], "\t") 
endf 

は今(改行に置換を減らしますSOのみ

%s/\v(.{-}),(.{-}),(.*)/\=join(
    [submatch(1), Consul(submatch(2)), Consul(submatch(3))], "\t")/g 

ご入力の上、その美しさを実行するための

を生み出します0
509 L. Iunius Brutus L. Tarquinius Collatinus 
suff. Sp. Lucretius Tricipitinus P. Valerius Poplicola 
suff. M. Horatius Pulvillus   
508 P. Valerius Poplicola T. Lucretius Tricipitinus 
507 P. Valerius Poplicola M. Horatius Pulvillus 

タブで区切られたカラムを好みのところにさらに飾るのは非常に簡単なステップです。私はそれを追加するかもしれないが、今のところ、ここで私は考えることができる最も簡単なことだ:

:%s/\v(.{-})\t(.{-})\t(.{-})\t(.{-})\t(.{-})\t(.{-})\t(.{-})$/1:{\1}\t2:{\2}\t3:{\3}\t4:{\4}\t5:{\5}\t6:{\6}\t7:{\7}/g 

結果:

1:{509} 2:{L.} 3:{Iunius} 4:{Brutus} 5:{L.} 6:{Tarquinius} 7:{Collatinus} 
1:{suff.} 2:{Sp.} 3:{Lucretius} 4:{Tricipitinus} 5:{P.} 6:{Valerius} 7:{Poplicola} 
1:{suff.} 2:{M.} 3:{Horatius} 4:{Pulvillus} 5:{} 6:{} 7:{} 
1:{508} 2:{P.} 3:{Valerius} 4:{Poplicola} 5:{T.} 6:{Lucretius} 7:{Tricipitinus} 
1:{507} 2:{P.} 3:{Valerius} 4:{Poplicola} 5:{M.} 6:{Horatius} 7:{Pulvillus} 
+0

はバグを洗い流し、解決策を完了するためのステップを追加しました – sehe

+0

うわー、私はこれらの結合とサブコマンドを見たことがありません。私はチャンスがあるときにこれを試してみます。 –

+0

Consul関数の中で 'split'コマンドは何をしますか?私は新しいウィンドウを開くsplitコマンドしか認識していません。どのように結合コマンドと組み合わせているのですか? –

3

はい、繰り返し内のキャプチャグループは、最新の一致した値に上書きされます。Repetition and Backreferencesセクションのリンク先ページの末尾にあります。

正規表現エンジンは、正規表現で後方参照を永続的に置き換えるものではありません。それは、使用する必要があるたびに逆参照に保存された最後のマッチを使用します。カッコをキャプチャして新しい一致が見つかると、以前に保存された一致が上書きされます。

特定の数のキャプチャグループを明示的に書き込む必要があります。

私はvimの正規表現エンジンに特に精通していないので、ここに簡単な例があります。
あなたのテキストがabc 12 345 6789 xyzであるとします。 {1,3}の繰り返し範囲で、Iは?と第二及び第三(\d+)オプションをしたこと

# with repetition 
/^\w+(\d+){1,3} \w+$/ 

# yields: 
# 0: abc 12 345 6789 xyz 
# 1: 6789 

# ----- 
# writing out each subpattern 
/^\w+(\d+)(\d+)?(\d+)? \w+$/ 

# yields: 
# 0: abc 12 345 6789 xyz 
# 1: 12 
# 2: 345 
# 3: 6789 

注意。

+0

うーん。 Vimが私に "Too Many"と言っていたので、私が外側のグループを反復したいという理由の1つは、 そうでなければ、私はおそらくそれを怠け者にして、グループ全体を2回書きました。 :) –

+0

私は説明のためにこの答えを+1します – sehe

関連する問題