이 정규식 oneliner를 개선할 수 있는 방법이 있나요?

이 정규식 oneliner를 개선할 수 있는 방법이 있나요?

다음 구문을 사용하는 비디오 파일이 많이 있습니다.

TV.Show.Title.SXEY.Episode.Title.1080p.Uploader.mkv

이는 SXEY상수가 아닙니다. 파일에 따라 달라지는 숫자입니다 X. Y이름을 다음으로 바꾸고 싶습니다.

TV Show Title - SXEY - Episode Title.mkv

이를 위해 rename다음 명령을 사용합니다.

rename 's/\./\ -\ /;s/\./\ -\ /;s/\.(?!mkv)/\ /g;s/1080p.*(?=\.mkv)//g' *.mkv

이 명령은 먼저 처음 두 개의 점을 로 변환한 ␣-␣다음 다른 모든 점을 공백으로 변환하고 마지막으로 에피소드 제목 끝과 파일 확장자 사이의 모든 내용을 제거합니다.

이것이 어떻게 개선될 수 있는지 어떤 아이디어가 있습니까? 정규식을 사용하여 처음 두 점을 변환하는 방법이 있다고 생각합니다. 나는 rename그것이 GNU 유틸리티라고 믿기 때문에 모든 Unix 시스템에 존재하지 않으며 더 이식 가능한 대안을 찾고 있습니다.

답변1

이 질문이 실제로 그것에 관한 것이어서 다행입니다 regex. 동일한 질문을 하여 머리가 아프지 않도록 하고 싶습니다.

for m in *.mkv; 
    do echo mv $m "$(awk -F'.' '{
        printf "%s %s %s - %s - %s %s.%s", $1, $2, $3, $4, $5, $6, $(NF)}' <<<$m)";
done

출력 문자열은 예측 가능하고 읽기 쉽고 수정하기 쉽습니다. 그냥 삭제하세요echo

편집하다

아래 의견과 관련하여 sed동일한 기술을 사용하고 대신 출력용 파일 이름을 처리할 수 있습니다 sed.awk

for m in *.mkv; 
    do echo mv $m "$(sed 's/\./ /1;s/\./ /1;s/\./ - /1;s/\./ - /1;s/\./ /1;s/\..*\././' <<<$m)";
done

답변2

다음을 수행할 수 있습니다.

$ rename -n 's/.(S\d+E\d+)./ - $1 - /; s/\./ /g; s/\.1080p.+\././' *mkv
TV.Show.Title.SXEY.Episode.Title.1080p.Uploader.mkv -> TV Show Title - SXEY - Episode Title 1080p Uploader mkv

아니면 다음과 같은 것일 수도 있습니다.

$ rename -n 's/1080p.*\.//; s/\.(?!mkv)/ /g; s/S\d+E\d+/- $& -/' *mkv
TV.Show.Title.SXEY.Episode.Title.1080p.Uploader.mkv -> TV Show Title - SXEY - Episode Title.mkv

공백을 탈출할 이유가 없다는 점에 유의하세요. 따라서 정규식 논리에서 실제로 아무것도 변경하지 않고도 명령을 단순화할 수 있습니다.

rename 's/\./ - /;s/\./ - /;s/\.(?!mkv)/ /g;s/1080p.*(?=.mkv)//g' *.mkv

.mkv그러나 이렇게 하면 원하지 않는 항목 앞에 공백이 추가됩니다(원래 버전에서도 이 작업이 수행됨). 아마도 이것은:

rename -n 's/\./\ -\ /;s/\./\ -\ /;s/\.(?!mkv)/\ /g;s/ 1080p.*(?=.mkv)//g' *.mkv

보다 이식성이 뛰어난 솔루션을 원한다면 다음을 사용할 수 있습니다 perl(perl은 거의 모든 *nix 시스템에서 사용할 수는 없지만).

perl -e 'for (@ARGV){$n=$_;s/1080p.*\.//;s/\.(?!mkv)/ /g;s/S\d+E\d+/- $& -/; rename($n,$_)}' *mkv

이식성을 극대화하려면 셸에서 모든 작업을 수행하세요(약간의 sed).

for f in *mkv; do 
    k=${f//./ }
    k=$( printf '%s' "$k" | sed 's/S\([0-9][0-9]*E[0-9][0-9]\)/ - \1 -/')
    k=${k/ 1080p*/.mkv}
    mv -- "$f" "$k"
done

중요한 팁: 당신이 하려는 일은 매우 나쁜 생각입니다. 파일 이름에 공백이 있으면 작업이 더 어려워지고 나중에 해당 파일에 대해 실행하려는 모든 종류의 작업이 더 어려워집니다. 다시 생각해보세요.

답변3

노력하다:

rename -v -n \
  's/\./ /g;s/S[X0-9]*E[Y0-9]*/- $& -/;s/ \d*p .* mkv$/.mkv/' *.mkv

출력에서는 어떤 일이 발생하는지 보여주는 시험 실행을 제공하지만 아직 파일이 이동되지 않았습니다.

rename(TV.Show.Title.SXEY.Episode.Title.1080p.Uploader.mkv, 
       TV Show Title - SXEY - Episode Title.mkv)

출력이 좋아 보이면 -v -nmid부터 삭제하세요.s대리자내 것이 되어라애드 혹가능성이 낮은 데모 문자열을 처리하는 방법"SXEY", (바꾸다《S02E23》또는 기타) 다음으로 바꾸십시오 s/S\d*E\d*/- $& -/.

rename 's/\./ /g;s/S\d*E\d*/- $& -/;s/ \d*p .* mkv$/.mkv/' *.mkv

노트:

  • \작은따옴표 " "를 사용하는 경우 " "와 같은 공백을 이스케이프 처리할 필요가 없습니다 ' '.

  • 위의 코드는 .모든 s를 공백으로 바꾼 다음 다음을 찾습니다.에스이슨찬/두번째piode 문자열을 삭제한 다음 마지막 파일 확장자를 복원합니다 .mkv. 이렇게 하면 고정 길이의 에피소드 및 프로그램 제목이 필요하지 않습니다.

답변4

유틸리티가 그룹 캡처를 지원하는지 확실하지 않지만 이를 사용하는 것이 실행 가능한 전략이 될 것입니다.

([^.]+)[.]([^.]+)[.]([^.]+)[.]([^.]+)[.]([^.]+)[.]([^.]+)[.]([^.]+)[.]([^.]+)[.]([^.]+)

그러면 당신은 사용할 것입니다

$1 $2 $3 - $4 - $5 $6.$7

이 전략의 장점은 실제로 다른 명명 체계의 의미를 해결하고 필드의 순서를 바꾸거나 생략할 수 있다는 것입니다. 가능하면 문자 그룹을 사용하여 문자를 이스케이프하는 것을 선호합니다 . [.].\.

관련 정보