vim正規表現の代替決定

vim正規表現の代替決定

昨年、私はVimwikiを使ってプロジェクトの毎週の進捗状況を記録し始めました。私の週間のWikiリンクリストの形式は、時間の経過とともにわずかに変更されました。年末、私はインデックスページを少し見て、私が作っていた主な項目の形式を統合することにしましたが、正規表現を正しく取得できませんでした。

更新したい箇条書きの元の例は、私が望む形式で上記の最新の項目で下に表示されます。

 * [[2018_Week_25|Week 25, 17th through the 23rd June]]
 * [[2018_Week_24|Week 24, 10th through 16th June]]
 * [[2018_Week_23|Week 23, 3rd through 9th June]]
 * [[2018 Week 22|Week 22, 27th May through 2nd June]]
 * [[2018 Week 21]], 20th through 26th May
 * [[2018_Week_20]]
 * [[2018_Week_19]]
 * [[2018_Week_18]], 29th April through 5th May
 * [[2018_Week_17]], 22nd through 28th April
 * [[2018_Week_16]], 15th through 21st April
 * [[2018_Week_15]], 8th through 14th April
 * [[2018_Week_14]], 1st through 7th April
 * [[2018_Week_13]], 25th through 31st March

私は簡単なマッチで始めました。

/\[\[\d+[_\s]Week[_\s]\d+\]\],\s\d+\w+.*/g

5、8-13行の対応する部分と一致します。その後、いくつかのパターン変数と代替項目を追加しようとしましたが、すべてが崩れました。次の代替行を使用すると、Vimは突然以前に見つかったパターンが見つからないと判断します。

:1,13s/\(2018[_\s]Week[_\s]\d\d\),\s\(\d+\w+\)/\[\[\1|\1\2\]\]/g
E486: Pattern not found: \(2018[_\s]Week[_\s]\d\d\),\s\(\d+\w+\)

私は実際にこれに微妙なバリエーションをたくさん試しましたが、私は単に明らかなものを見落としていると信じ始めました。誰でもどんな提案がありますか?

答え1

:%s/\(\[\[\d\+[_ ]\+Week\([_ ]\+\)\(\d\+\)\)\]\],\(.*\)/\1|Week\2\3,\4]]/

\s*手動で入力したテキストで常に発生する不一致をよりよく捉えるために、適切な場所にパディングを追加することでこの式を改善できます。

提案されたソリューションにはいくつかの問題があります。

  • 正規表現: 次\(2018[_\s]Week[_\s]\d\d\),\s\(\d+\w+\) の理由で一致しません。

    • バックスラッシュでエスケープされた事前定義文字クラスは、区切り文字のカスタム文字クラス内では使用できません[][_\s]アンダースコア、バックスラッシュ、またはs文字と一致します。_\|\sこのような状況で使用できます。
    • +「1以上」の数量子が有効になっているため、特別な意味のためにこの文字をエスケープする必要があります。それ以外の場合は+リテラル記号と一致します。
    • セクションの前には、一致させるテキストのシーケンス一致がありますが、,\s\(\d+\w+\)そのシーケンス一致はパターンから欠落しています。\]\]\]\]
  • 文字列内のバックスラッシュを置き換える問題を無視し、結果の文字列を終了して終了しようとします]]が、指定されたコンマの後の日付と一致する部分のみを使用します\d\+\w\+。つまり、置換が成功すると、行は途中のどこかで行を終了する必要があるシーケンスとともに、29th]] April through 5th May次のテキストで終わります。]]

  • 代替文字列:\[\[\1|\1\2\]\] 正規表現ではないため、[同じ文字を]エスケープする必要はありません。

  • また、間違っているわけではありませんが、すべてがすでに含まれており、式の前半を使用してコンテキストを指定する方法で重複しているため、\d\+\w\+常に etc と一致し、誤ったコンテンツと一致しません。\w\d9th

編集:@ user1133275の非常に良い提案は、(一部の変更を含む)元のソリューションのキャプチャグループにコンマを使用することです。これにより、日付間隔が指定されていない行も変更されます。 「x番目からy番目」はありません。

:%s/\(\[\[\d\+[_ ]\+Week\([_ ]\+\)\(\d\+\)\)\]\]\(,.*\)\?/\1|Week\2\3\4]]/

@ user1133275は回答を提供していないので、ディスカッションの結果をこの回答のコメントセクションに入れます。彼らがそれを答えに入れることを決め、私に通知されたら、この編集内容を削除して、基本的なアイデアの作成者にクレジットを返すようにします。

答え2

あなたの質問を正しく理解したら、次の代替方法で必要な作業を行う必要があります。

%s/\[\[\(\d\+\)\([_ ]\)Week\([_ ]\)\(\d\+\)\]\],\(\s\d\+\w\+.*\)/[[\1\2Week\3\4|Week \4,\5]]/

注:\([_ ]\)キャプチャグループは、前のコンポーネントに表示された区切り文字(スペースまたはアンダースコア)を保持します|。区切り文字は5行のスペースで、下線は8〜13行で使用されます。

答え3

vim正規表現は非標準なので、vimで業界最高のperlを使用してください。

:%!perl -pe '$RE'

vimの外部でテストできます。

> echo "[[2018_Week_18]], 29th April through 5th May" \
| perl -pe 's/[_ ](Week)[_ ](\d+)\]\](, .*)?/_$1_$2|$1 $2$3]]/g'
[[2018_Week_18|Week 18, 29th April through 5th May]]

Perl REはvim REの長さの約2分の1だけでなく、Perl REは他の多くのツール(grep/rename/vim/sed/awk/etc)ともコピー/貼り付けと互換性があります。

関連情報