Grep은 따옴표가 있어도 변수를 사용하지 않습니다.

Grep은 따옴표가 있어도 변수를 사용하지 않습니다.

name=$(echo "$FILENAME" | grep -E '*\.(eng|por|pt-BR)\.*')

이 줄은 왜 작동하지 않나요?

만약 내가한다면

echo "Test (2013).1080p.por.mkv" | grep -E "*\.(eng|por)\.*"

작동합니다. "" 없이 ""를 사용하고 스크립트에서 '를 사용해 보았지만 grep으로 파이프되지 않은 것 같습니다. 왜인지 모르겠습니다. bash를 사용하고 있습니다.

FILENAME="Test (2013).1080p.por.mkv"

난 그냥 .por을 가져오고 싶어요. 또는 파일의 .eng

답변1

grep패턴과 일치하는 (전체) 라인을 인쇄하는 도구입니다. 문자열의 일부를 추출하는 것은 적절하지 않습니다(일부 grep구현 에서는 경우에 따라 이 옵션을 사용 -o<n>하거나 사용할 수 있음).-o

여기에서 다음을 사용할 수 있습니다 expr.

name=$(expr " $FILENAME" : '.*\.\(eng\)\.' '|' \
            " $FILENAME" : '.*\.\(por\)\.' '|' \
            " $FILENAME" : '.*\.\(pt-PT\)\.')

( 의 경우 foo.por.eng.bar가 보다 우선합니다 eng.)porpt-PT

일부 expr구현(예: GNU)은 expr다음도 지원합니다.

name=$(expr " $FILENAME" : '.*\.\(eng\|por\|pt-PT\)\.')

(파일 이름이 두 개 이상인 경우 가장 오른쪽에 일치하는 항목이 반환됩니다.)

GNU grep또는 호환 제품을 사용하세요.

name=$(
  printf '%s\n' "$FILENAME" |
    grep -Po '\.\K(eng|por|pt-PT)(?=\.)' |
    head -n 1
)

(첫 번째 항목을 반환하고 마지막 항목 head으로 대체)tail

case또는 명령을 실행하지 않고 쉘 구성을 사용할 수 있습니다 .

case $FILENAME in
  (*.por.*) name=por;;
  (*.eng.*) name=eng;;
  (*.pt-PT.*) name=pt-PT;;
esac

그리고 bash:

re='\.(por|eng|pt-PT)\.'
[[ $FILENAME =~ $re ]]
name=${BASH_REMATCH[1]}

(첫 번째 발생. , 로 대체 zsh)BASH_REMATCHmatch

답변2

파일 이름이 다음과 같고 Some name.por.mkv최종 확장자가 고정되어 있다고 가정하면 POSIX 쉘 문자열 조작을 사용할 수도 있습니다.

$ echo "$FILENAME"
Test (2013).1080p.por.mkv
$ x=${FILENAME%.mkv}; echo "${x##*.}"
por

여기에서 ${var%.mkv}후행을 제거 .mkv하고 ${var##*.}(현재) 마지막 지점까지 모든 것을 삭제합니다. .mkv첫 번째 확장으로만 변경하여 다른 확장을 처리 할 수 있습니다 .*.

관련 정보