초보자 질문: ZSH 스크립트의 정규식

초보자 질문: ZSH 스크립트의 정규식

내 문제는 간단한 것 같아요. 고정된 접두어와 이전 파일 이름의 일부인 숫자(2자리)를 포함하는 새 파일 이름을 만들고 싶습니다.

예: "blableblub23.pdf" 파일이 있고 이름을 "Newfile 23"으로 변경하여 이동하고 싶습니다. 여기서 "Newfile"은 고정 접두사입니다.

따라서 먼저 이전 파일 이름에서 숫자가 아닌 모든 항목을 제거해야 하는데 이것이 주요 문제입니다. 나는 노력하고있다

paperno=expr match "$filename" '.*([0-9][0-9]).*'
filename_new="Newfile $paperno"

나는 항상 숫자 없이 filename_new = "Newfile"을 얻지만 "Newfile 23"을 기대합니다.

내 잘못이 뭐예요?

정말 고마워요 ;)

명확히 하기 위해 편집됨:

파일 이름 어디에든 두 자리 숫자가 포함된 파일 이름($filename에 저장됨)이 있습니다.

Test_bla_blub_23_and_more.pdf Test_23.pdf Test_23_bla.pdf

새 파일 이름을 만들기 위해 다른 변수 $paperno에 숫자(예: 23)를 저장하고 싶습니다.

파일 이름에 숫자가 없거나 그 이상의 숫자가 있는 경우 $paperno 변수는 비어 있거나 0이어야 합니다. 숫자가 여러 개인 경우 모든 숫자를 반환하면 수락됩니다. 즉:

Test_12_bla_blub_23_and_more.pdf => $paperno = 1223

죄송합니다. 저는 쉘 스크립팅, zsh 및 정규 표현식을 처음 접했습니다.

답변1

zsh정규식 일치(ERE 및 PCRE)에 대한 일부 기본 지원이 있으며 정규식 이상으로 확장된 glob 연산자도 있습니다. 오래되고 손상된 설계 명령을 사용할 필요가 없습니다 expr(BRE 사용,기초적인정규식 자체).

일괄 이름 바꾸기 도구도 있습니다.

autoload -Uz zmv
zmv -v '(*[^0-9]|)(<->).pdf' 'Newfile $1'

(*)(<->).pdf.*([0-9][0-9])\.pdf작동하지 않습니다. foo1234.pdf예를 들어 *(resp. )는 (resp. ) .*와 일치하여 가능한 가장 작은 ( ) 만 남기기 때문 입니다. (각각 ) .foo123foo124<->34[0-9][0-9]

PCRE를 사용하는 경우 다음과 같이 탐욕스럽지 않은 일치 연산자를 사용할 수 있습니다.

set -o rematchpcre
[[ $file =~ '^.*?(\d+)\.pdf\z' ]]
number=$match[1]

.*그러나 정규식을 처음에 고정하지 않으면 필요하지 않습니다(위에서는 ^암시 expr적으로 처음에 고정됨).

[[ $file =~ '(\d+)\.pdf$' ]]

( PCRE 이후 $ERE의 기본값 ).\zset -o rematchpcre

또는 여기에서 다음을 수행할 수 있습니다.

zmv '*<->.pdf' 'Newfile ${(M)${f:r}%%<->}'

${f:r}연장할 곳루트 이름(확장자 제거) ${(M)param%%pattern}일치하는 인수의 가장 긴 꼬리까지 확장합니다 pattern( <->여기서는 제한 없이 모든 ASCII 십진수 시퀀스와 일치합니다 <x-y>).

파일 이름에서 모든 숫자를 추출하려면(예 : 또는 다음 foo-123-bar.pdf으로 이름 바꾸기 )Newfile 123foo1bar2.pdfNewfile 12

zmv -v '*[0-9]*.pdf' 'Newfile ${f//[^0-9]}'

을(를) 확장 ${f//pattern/replacement}하고 $f모든 항목을 pattern바꿉니다 replacement. 여기서는 치환을 생략하므로 십진수를 제외한 모든 문자를 아무것도 치환하지 않습니다.

.pdf완전성을 위해 이전 에 숫자 목록을 추출하려면 expr다음을 수행해야 합니다.

number=$(expr "x$file" : '.*[^0123456789]\([0123456789]\{1,\}\)\.pdf$')

해당 번호를 찾지 못하면 실패한 종료 상태를 반환하고, 해당 번호를 찾지 0못하면 00...000

이 접두사는 확장이 연산자 인 경우 연산자로 처리되는 설계 버그를 x해결하기 위한 것입니다 .expr$fileexpr

이는 match표준 expr연산자가 아니며 표준 연산자는 이 :연산자입니다.

다시 말하지만, 70년대에는 매우 손상되고 제한적인 유틸리티였으며 특히 매우 강력한 텍스트 추출 및 서식 지정 기능이 내장되어 있기 expr때문에 오늘날에도 계속 사용할 이유가 없습니다 .zsh

답변2

표현식 출력문자 수가 일치합니까? paperno 변수를 인쇄해 보셨습니까? 나는 그것이 당신에게 예상되는 결과를 줄 것이라고 생각하지 않습니다

가능한 방법은 모든 문자열을 제거하고 "."으로 잘라내어 숫자를 얻는 것입니다. 좋다:

charstostrip=expr match "$filename" '^[a-zA-Z]+$'
modified=${$filename:$charstostrip}
fn_number=${echo $modified | cut -d . -f1}
filename_new="Newfile $fn_number"

관련 정보