작년에 저는 Vimwiki를 사용하여 프로젝트의 주간 진행 상황을 기록하기 시작했습니다. 내 주간 위키 링크 목록의 형식은 시간이 지남에 따라 약간 변경되었습니다. 연말에 나는 색인 페이지를 잠깐 살펴보고 내가 만들고 있던 주요 항목의 형식을 통합하기로 결정했지만 정규식을 제대로 얻을 수 없었습니다.
업데이트하려는 글머리 기호의 원래 예는 내가 원하는 형식으로 위의 최신 항목과 함께 아래에 표시됩니다.
* [[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
\d
9th
편집: @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 길이의 약 1/2일 뿐만 아니라 Perl RE는 다른 많은 도구(grep/rename/vim/sed/awk/etc)와도 복사/붙여넣기와 호환됩니다.