개별 문자/숫자 대신 괄호를 사용하여 패턴을 일치시키는 방법은 무엇입니까?

개별 문자/숫자 대신 괄호를 사용하여 패턴을 일치시키는 방법은 무엇입니까?

MSG내 경로에서 제외 하고 괄호를 사용하여 쉘 매개변수 확장을 사용하고 싶습니다 PDF.DOC

MSG괄호 사이에 넣으면 M삭제되지 않고 삭제만 됩니다 MSG. 인터넷을 둘러보고 설명서를 읽었지만 여전히 이 작업을 올바르게 수행하는 방법을 이해할 수 없습니다. 어쩌면 내가 검색하기에 적합한 키워드를 모르는 것일 수도 있습니다.

내 코드는 MSG만 제거합니다.

find "${INPUTPATH}" -mindepth 2 -maxdepth 2 -type d -print0 | while IFS= read -r -d '' file; do
    echo "${file}"
    casenumber="${file#${INPUTPATH}/[MSG]}"
    echo "${casenumber}"
done

입력하다:

/home/user/output/test/PDF/2218-0
/home/user/output/test/PDF/2218-0
/home/user/output/test/DOC/2218-0
/home/user/output/test/DOC/2218-0
/home/user/output/test/MSG/2226-4
/home/user/output/test/MSG/2226-4
/home/user/output/test/MSG/2222 -2
/home/user/output/test/MSG/2222 -2
/home/user/output/test/MSG/2218-0
/home/user/output/test/MSG/2218-0

현재 MSG를 제거하는 출력:

/home/user/output/test/PDF/2218-0
/home/user/output/test/PDF/2218-0
/home/user/output/test/DOC/2218-0
/home/user/output/test/DOC/2218-0
/home/user/output/test/MSG/2226-4
SG/2226-4
/home/user/output/test/MSG/2222 -2
SG/2222 -2
/home/user/output/test/MSG/2218-0
SG/2218-0

예상 출력:

/home/user/output/test/PDF/2218-0
/home/user/output/test/PDF/2218-0
/home/user/output/test/DOC/2218-0
/home/user/output/test/DOC/2218-0
/home/user/output/test/MSG/2226-4
/2226-4
/home/user/output/test/MSG/2222 -2
/2222 -2
/home/user/output/test/MSG/2218-0
/2218-0

실제로 MSG, PDF, DOC를 이런 식으로 삭제하고 싶습니다.

find "${INPUTPATH}" -mindepth 2 -maxdepth 2 -type d -print0 | while IFS= read -r -d '' file; do
    echo "${file}"
    casenumber="${file#${INPUTPATH}/[MSG][PDF][DOC]/}"
    echo "${casenumber}"
done

위 코드가 작동하지 않는 이유를 이해합니다. 하지만 이 작업을 수행하려면 먼저 MSG를 해결해야 합니다.

최종 예상 출력:

/home/user/output/test/PDF/2218-0
2218-0
/home/user/output/test/DOC/2218-0
2218-0
/home/user/output/test/MSG/2226-4
2226-4
/home/user/output/test/MSG/2222 -2
2222 -2
/home/user/output/test/MSG/2218-0
2218-0

답변1

[MSG]전역 패턴은 하나의 문자 M또는 S와 일치합니다 G. MSG, DOC또는 를 일치시키려면 in 또는 in ksh를 PDF사용할 수 있습니다 . bash는 zsh glob 연산자를 지원하지 않지만 after를 포함한 ksh 연산자의 하위 집합을 지원하므로 bash에서는 다음과 같습니다.(MSG|DOC|PDF)zsh@(MSG|DOC|PDF)shopt -s extglob

shopt -s extglob
casenumber=${file#"${INPUTPATH}"/@(MSG|DOC|PDF)}

에 할당되어 내용과 일치하는 가장 짧은 선행 부분을 제거하고 casenumber(말 그대로 zsh와 달리 ksh/bash에서 필요한 주변 따옴표 덕분에) , 또는 가 뒤따릅니다.$file$INPUTPATH/MSGDOCPDF

shopt -s extglobksh에서는 bash에만 해당되고 ksh에서는 필요하지 않은 항목을 생략하세요 . zsh에서:

casenumber=${file#$INPUTPATH/(MSG|DOC|PDF)}

답변2

실제로 와일드카드는 아니지만...

=~확장된 테스트 대괄호 내에서 사용하면 최신 버전의 Bash는 RegEx 연산자를 사용하여 정규식 기반 일치를 수행할 수 있습니다 [[ ... ]]. 캡처 그룹을 수행할 수 있으며 0번째 인덱스가 하나의 인덱스 아래 전체 일치를 참조하는 (...)내장 배열이 있습니다. 첫 번째 캡처링 그룹 일치를 참조하고, 다음은 두 번째 캡처링 그룹 일치를 참조하는 식입니다.BASH_REMATCH${BASH_REMATCH[0]}${BASH_REMATCH[1]}${BASH_REMATCH[2]}

따라서 다음과 같이 할 수 있습니다.

$ printf '%s\0' "/home/user/output/test/PDF/2218-0" "/home/user/output/test/DOC/2218-0" "/home/user/output/test/MSG/2226-4" |
while IFS= read -r -d '' file; do
  [[ "$file" =~ .*(DOC|MSG|PDF)(.*) ]] && printf '%s\n' "$file" "${BASH_REMATCH[2]}"
  done
/home/user/output/test/PDF/2218-0
/2218-0
/home/user/output/test/DOC/2218-0
/2218-0
/home/user/output/test/MSG/2226-4
/2226-4

답변3

정확한 질문에 대답하는 것이 아니라 이 특정 사례에 대한 몇 가지 참고 사항입니다.

현재 위치에 있다는 점을 고려하면 find "${INPUTPATH}" -mindepth 2 -maxdepth 2생성된 모든 경로에는 초기 경로 뒤에 슬래시가 하나만 있어야 하므로 $INPUTPATH거기에 있는 특정 세 글자 문자열을 무시하고 다음 문자열 앞의 모든 항목을 제거하면 됩니다 /.

casenumber=${file#"${INPUTPATH}"/*/}

아니면 마지막 슬래시이므로 그냥 제거하세요.모든 것끝까지 /:

casenumber="${file##*/}"

여기서 두 배로 한다는 것은 #가장 긴 경기를 치르는 것을 의미합니다.

또한 이전에 실행한 경우 $INPUTPATH출력에서 ​​해당 부분을 제거할 수 있습니다(다음으로 교체하기만 하면 됨) ..cdfind

(cd -P -- "${INPUTPATH}" && find . -mindepth 2 -maxdepth 2 -type d -print0) |
 while IFS= read -r -d '' file; do
    echo "${file}"
    casenumber="${file#./*/}"
    echo "${casenumber}"
done

관련 정보