잘못 인코딩된 문자열이 포함된 큰 재생 목록 .pls
(재생 소프트웨어로 생성 ) 이 있습니다 . 이것이 버그 인지 플러그인 중 하나 인지 deadbeef
는 모르겠지만 .deadbeef
sed
그러나 이는 언뜻 보기보다 쉽습니다 sed
.방해하다문자를 발견하자마자 "유효하지 않은" 것으로 간주하는 문자를 구문 분석합니다.
$ cat archives.pls | grep --perl-regexp Lika.*rar.*02
rar:///home/andy/audio_compressed/world/ru/Lika Star - Ya (RUS 2001).rar:2001- �/02 ���.mp3
수정되지 않은 원본 라인입니다. 이제 경로를 추출하여 시도해 보겠습니다 sed
. (참고: 이것은 디렉토리 트리에서 "죽은" 오디오 파일, 즉 더 이상 존재하지 않는 파일을 확인하기 위해 완료하려는 스크립트입니다.)
$ cat archives.pls | grep --perl-regexp Lika.*rar.*02 | sed -e 's/^\(zip\|rar\|7z\):\/\///' -e 's/\(\.\(zip\|rar\|7z\)\):.*/\1/'
/home/andy/audio_compressed/world/ru/Lika Star - Ya (RUS 2001).rar�/02 ���.mp3
아. 이것은 분명히 작동하지 않습니다. 정규식은예절대적으로 정확합니다(소위 "유효한" 문자로 제대로 작동하는 것으로 입증될 수 있으므로). 실제로 콜론부터 "2001-"까지 공백으로 구문 분석한 후 갑자기 유효하지 않은 � 문자에서 멈추는 것을 의미하는 rar�
Original의 약어에서 유래되었습니다 . 여전히 질문이 남아 있습니다. 인코딩이 무엇인지 무시하고 어쨌든 구문 분석하면 어떨까요? 내 말은, 우리는 "rar" 뒤의 콜론 뒤의 모든 내용을 잘라내기를 원하므로 가정하는 것이 안전해야 합니다.rar:2001- �
sed
sed
.*
하다
절대적으로 대표적이다어느특징?
cut
참고: 답변에 "우아해 보이는" 솔루션을 사용 하지 마십시오 . 거기 있었어, 그랬어. 대신, 우리는 UNIX 유형의 운영 체제를 사용하고 있으며 원래 ":wumpscut:" 또는 이와 유사한 철자를 사용한 아티스트와 관련된 이상한 파일 이름을 법적으로 사용할 수도 있다는 점을 고려하는 것이 좋습니다. 즉, 중간에 또 다른 콜론이 있을 수 있으므로, 이후에 처음 만나는 콜론을 정적으로 잘라내는 것은 좋은 생각이 아닙니다 (zip|rar|7z)://
.
답변1
Goldilocks가 이미 위에서 언급했듯이 UTF-8은멀티바이트가변 너비 인코딩. 각 문자는 최대 4바이트로 구성될 수 있습니다. 유효하지 않은 바이트 후에는 최대로 할 수 있습니다희망다음 바이트는 새로운 문자를 시작할 수 있습니다.
sed
바이트 대신 문자를 일치시켜 보세요. 유효하지 않은 바이트는 문자가 아니고 .
일치하는 유일한 문자이므로 일치하지 않으며 결과는 절대적으로 정확합니다.
파일이 어떤 인코딩을 사용하는지 알아내야 합니다. (이 file
명령은 이 작업을 수행하는 데 도움이 될 수 있습니다.) 환경 변수를 올바른 값으로 설정하면 예상대로 작동하기 LANG
에 충분합니다 . sed
귀하의 경우에는 아마도 LANG=C
충분할 것입니다.
답변2
환경 변수를 LANG
UTF-8로 인코딩된 문자열(예: LANG='en_US.UTF-8'
Mac OS X 10.6.8)로 설정하면 질문에서 언급한 대로 LANG='C'
GNU 4.2.1의 구문 분석이 중지됩니다 . 반면에 GNU 4.2.2는 잘 작동합니다.sed
sed
나에게 도움이 된 또 다른 수정(Mac OS X 10.6.8)은 정규식 부분을 :.*
다음으로 바꾸는 것이었습니다: :\([^[:print:]]\|[[:print:]]\)*
(POSIX 문자 클래스).
echo $'rar:///home/andy/audio_compressed/world/ru/Lika Star - Ya (RUS 2001).rar:2001- \357\277\275/02 \357\277\275\357\277\275\357\277\275.mp3' > archives.pls
(
export LANG='C'
#locale charmap
cat archives.pls | grep --perl-regexp 'Lika.*rar.*02'
cat archives.pls | grep --perl-regexp 'Lika.*rar.*02' | gsed -e 's/^\(zip\|rar\|7z\):\/\///' -e 's/\(\.\(zip\|rar\|7z\)\):.*/\1/' # GNU sed 4.2.1
cat archives.pls | grep --perl-regexp 'Lika.*rar.*02' | gnused -e 's/^\(zip\|rar\|7z\):\/\///' -e 's/\(\.\(zip\|rar\|7z\)\):.*/\1/' # GNU sed 4.2.2
cat archives.pls | grep --perl-regexp 'Lika.*rar.*02' | gsed -e 's/^\(zip\|rar\|7z\):\/\///' -e 's/\(\.\(zip\|rar\|7z\)\):\([^[:print:]]\|[[:print:]]\)*/\1/'
)
# output:
# rar:///home/andy/audio_compressed/world/ru/Lika Star - Ya (RUS 2001).rar:2001- �/02 ���.mp3
# /home/andy/audio_compressed/world/ru/Lika Star - Ya (RUS 2001).rar�/02 ���.mp3
# /home/andy/audio_compressed/world/ru/Lika Star - Ya (RUS 2001).rar
# /home/andy/audio_compressed/world/ru/Lika Star - Ya (RUS 2001).rar
#--------------
(
export LANG='en_US.UTF-8'
#locale charmap
cat archives.pls | grep --perl-regexp 'Lika.*rar.*02'
cat archives.pls | grep --perl-regexp 'Lika.*rar.*02' | gsed -e 's/^\(zip\|rar\|7z\):\/\///' -e 's/\(\.\(zip\|rar\|7z\)\):.*/\1/' # GNU sed 4.2.1
cat archives.pls | grep --perl-regexp 'Lika.*rar.*02' | gnused -e 's/^\(zip\|rar\|7z\):\/\///' -e 's/\(\.\(zip\|rar\|7z\)\):.*/\1/' # GNU sed 4.2.2
cat archives.pls | grep --perl-regexp 'Lika.*rar.*02' | gsed -e 's/^\(zip\|rar\|7z\):\/\///' -e 's/\(\.\(zip\|rar\|7z\)\):\([^[:print:]]\|[[:print:]]\)*/\1/'
)
# output:
# rar:///home/andy/audio_compressed/world/ru/Lika Star - Ya (RUS 2001).rar:2001- �/02 ���.mp3
# /home/andy/audio_compressed/world/ru/Lika Star - Ya (RUS 2001).rar
# /home/andy/audio_compressed/world/ru/Lika Star - Ya (RUS 2001).rar
# /home/andy/audio_compressed/world/ru/Lika Star - Ya (RUS 2001).rar