정규 표현식: 얼마나 많은지 알지 못한 채 일치하는 모든 그룹을 인용합니다.

정규 표현식: 얼마나 많은지 알지 못한 채 일치하는 모든 그룹을 인용합니다.

다음 패턴에 따라 파일의 문자열을 바꾸고 싶습니다.

  • <<key q>><kbd>q</kbd>
  • <<key Ctrl q>><kbd>Ctrl</kbd>+<kbd>q</kbd>
  • <<key Ctrl Shift Alt q>><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Alt</kbd>+<kbd>q</kbd>

업데이트: 파일에는 추가 텍스트도 포함되어 있습니다. 예: Press <<key Ctrl q>> to quit.

이 문제를 해결하기 위해 찾을 수 있는 가장 좋은 해결책은 sed호출할 1, 2, 3, 4 키에 대해 별도의 스크립트를 사용하는 것입니다.

sed -i -E \
    -e 's|<<key ([^ ]+)>>|<kbd>\1</kbd>|g'
    -e 's|<<key ([^ ]+) ([^ ]+)>>|<kbd>\1</kbd>+<kbd>\2</kbd>|g' \
    -e 's|<<key ([^ ]+) ([^ ]+) ([^ ]+)>>|<kbd>\1</kbd>+<kbd>\2</kbd>+<kbd>\3</kbd>|g' \
    -e 's|<<key ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+)>>|<kbd>\1</kbd>+<kbd>\2</kbd>+<kbd>\3</kbd>+<kbd>\4</kbd>|g' \
    file.txt

분명히 이것은 5개 이상의 키를 포함하는 매크로에서는 실패할 것입니다.

더 일반적인 솔루션이 있습니까?N열쇠? 에 국한되지 않고 sed구조적 정규식(sregx) 그러나 그것을 수행하는 방법을 찾을 수 없습니다.

답변1

나는 그러한 작업을 수행하기 위해 Perl을 사용할 것입니다.

#!/bin/perl
while(<>) {
    if (/<<key (.*?)>>/) {
        my $pattern_with_keys = $1;
        my @keys = split / /, $pattern_with_keys ;
        my @kbd_keys = map {"<kbd>$_</kbd>"} @keys;
        print join('+', @kbd_keys), "\n";
    }
}

그것을 실행 perl script.pl < source_file.txt하고 즐기십시오.

답변2

  1. 한 번에 하나씩 교체하십시오.
  2. 새로운 교체가 완료되지 않을 때까지 이 작업을 반복합니다.
  3. 정크를 제거하십시오.

이와 같이:

sed -E ':start s|(<<key[^>]*) ([^>]*)>>|\1>>+<kbd>\2</kbd>|g; t start; s|<<key>>\+||g'

어디:

  • :start라벨입니다.
  • s|(<<key[^>]*) ([^>]*)>>|\1>>+<kbd>\2</kbd>|g이 되다.<<key Ctrl Shift Alt q>><<key Ctrl Shift Alt>>+<kbd>q</kbd>
  • t starts방금 교체한 것이 있는 경우에만 태그로 이동하십시오 .
  • ... <<key Ctrl Shift Alt>>+<kbd>q</kbd>가 되고
    <<key Ctrl Shift>>+<kbd>Alt</kbd>+<kbd>q</kbd>, 그러면
    <<key Ctrl>>+<kbd>Shift</kbd>+<kbd>Alt</kbd>+<kbd>q</kbd>마침내
    <<key>>+<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Alt</kbd>+<kbd>q</kbd>. 다음 반복에서는 s아무것도 대체되지 않으므로 ( <<key>>공간이 없기 때문에 일치하지 않음) 작업 t이 필요하지 않습니다.
  • s|<<key>>\+||g잔여물을 제거하십시오.

참고: ( [^>]*대 상대 .*)는 <<key …>>동일한 줄에 있는 여러 조각 간의 일치를 방지합니다.

관련 정보