
많은 예를 보았지만 이렇게 할 수는 없는 것 같습니다. grep은 지정된 그룹과 일치하는 출력만 출력할 수 있습니까? 예를 들어 작동해야 할 것처럼 보이지만 오류가 발생하거나 전혀 출력되지 않습니다.
나하고 싶어:
pathname="/a/long/path/of/mine/2x02 - bar.mp4"
모든 예는 긴 경로, 한두 자리 숫자, x, 두 자리 숫자, 공백, - 및 파일 이름으로 구성됩니다.
02 값을 구문 분석하고 싶습니다. https://regex101.com/ 이 경우 \d{1,2}x(\d\d)는 1 = 02와 일치해야 함을 보여줍니다.
내가 모르는 것은 내가 그랬다면
echo "$pathname" | sed -n 's/.*\d{1,2}x\(\d\d\)/\1/p'
또는
echo $pathname | grep -oP '\d{1,2}x(\d\d)'
나는 아무것도 얻지 못했습니다. 저 할 수 있어요:
echo $pathname | grep -oP '(\d\d)'
하지만 어떤 경우에는 저처럼 연속해서 다른 2자리 값이 나올 수도 있습니다.
/a/long/path/of/mine/12x02 - bar.mp4
이 경우 위의 내용이 두 번째 일치 항목을 지정하지 않을 것이라고 생각하므로 일치 그룹 등을 사용할 수 있다면 더 구체적인 정규식을 선호합니다. Scientific Linux 7.1의 bash에서 이 작업을 수행하려고 합니다.
답변1
grep
PCRE( ) 를 사용하는 것과 마찬가지로 -P
다음 정규식 패턴을 사용할 수 있습니다.
grep -Po '\d{1,2}x\K\d{2}(?= )' <<<"$pathname"
\d{1,2}x
다음 한 자리 또는 두 자리 숫자x
와 일치한 다음\K
일치 항목을 삭제합니다.\d{2}
두 숫자가 정확히 일치하는 경우 너비가 0인 전방 예측 패턴을 사용(?= )
하면 두 숫자 뒤에 공백이 있습니다.
따라서 이는 귀하의 요구 사항을 충족해야 합니다.
예:
$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/2x02 - bar.mp4'
02
$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/34x12 - bar.mp4'
12
$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/0x1 - bar.mp4'
## No match
$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/00x1 - bar.mp4'
## No match
답변2
sed 사용
기본 모드에서 sed를 사용하는 경우 중괄호를 이스케이프해야 합니다.
$ echo "$pathname" | sed -n 's/.*[[:digit:]]\{1,2\}x\([[:digit:]][[:digit:]]\).*/\1/p'
02
더 나은 이식성을 위해 [[:digit:]]
뒤에 오는 텍스트를 제거하기 위해 끝에 \d
추가합니다 ..*
사용grep -P
grep -P
뒤돌아보기 기능은 지원되지만 뒤돌아보기 텍스트는 고정된 길이여야 합니다. 따라서 x
표시하려는 처음 두 자리 앞에 한 자리 숫자를 찾을 수 있습니다 .
$ echo "$pathname" | grep -oP '(?<=\dx)(\d\d)'
02
대체 경로
위의 두 가지 방법은 대체 경로에도 적용됩니다.
$ echo '/a/long/path/of/mine/12x02 - bar.mp4' | grep -oP '(?<=\dx)(\d\d)'
02
$ echo '/a/long/path/of/mine/12x02 - bar.mp4' | sed -n 's/.*[[:digit:]]\{1,2\}x\([[:digit:]][[:digit:]]\).*/\1/p'
02
답변3
POSIX 쉘만 사용
p=$pathname
p=${p##*/}
p=${p#*x}
p=${p%% *}
echo "$p"
#or on one line
p=${pathname##*/};p=${p#*x};p=${p%% *};echo "$p"