나는 이 문자열을 가지고 있습니다 :
DMT mode 4: 640x480 @ 60Hz 4:3, clock:25MHz progressive
패턴 번호(첫 번째 :) 앞의 부분을 추출하고 싶습니다. 이 경우 4입니다. 예상한 대로 패턴 번호의 길이는 1자리 또는 2자리일 수 있으며 그 앞의 텍스트 문자 길이가 정확히 동일하다고 믿을 수는 없습니다.
작동하는 솔루션이 있습니다.
$picked = "DMT mode 4: 640x480 @ 60Hz 4:3, clock:25MHz progressive"
echo $picked | awk -F"mode " '{print $2}' | tr : '\n' | head -n1
그러나 나는 이것을 수행하는 더 우아한 방법이 있어야 한다고 생각합니다. 우아하고 배우기 쉬우며 나중에 읽으십시오(따라서 아마도 정규 표현식이 포함되지 않을 것입니다). 내 꿈의 명령은 다음과 같습니다.echo $picked | "패턴" ":" 사이
다음은 구문 분석 가능한 입력 범위의 필요성을 보여주는 몇 가지 추가 예입니다.
CEA mode 7: 720x480 @ 60Hz 16:9, clock:27MHz x2 interlaced
CEA (native) mode 16: 1920x1080 @ 60Hz 16:9, clock:148MHz progressive
DMT mode 58: 1680x1050 @ 60Hz 16:10, clock:146MHz progressive
답변1
정규 표현식은 보다 간단한 솔루션입니다. 몇 가지 옵션은 다음과 같습니다.
echo "$picked" | grep -oP '(?<=mode )\d+'
echo "$picked" | grep -oP '(?<=mode )[[:digit:]]+'
PCRE 기능이 마음에 들지 않는 경우:
echo "$picked" | grep -oE 'mode [[:digit:]]+' | tr -d 'mode '
이 tr
명령은 삭제되지 않습니다.단어모든 것을 제거하는 "모드"수치"모델", " ".
당신이 정말 좋아한다면앗, "패턴"을 클릭할 때까지 단어를 반복합니다.
echo "$picked" | awk '{for (i=1; i<NF; i++) if ($i == "mode") {print $(i+1); exit}}' | tr -d :
문자열이 이미 쉘 변수에 포함되어 있으므로 bash 매개변수 대체는 어떻습니까?
tmp=${picked#*mode } # remove up to "mode "
value=${tmp%%:*} # remove the colon and everything after
그 다음에
$ declare -p picked tmp value
declare -- picked="DMT mode 4: 640x480 @ 60Hz 4:3, clock:25MHz progressive"
declare -- tmp="4: 640x480 @ 60Hz 4:3, clock:25MHz progressive"
declare -- value="4"
인용하다3.5.3 쉘 매개변수 확장설명서에서(그리고 일부 세부 사항을 간략히 설명):
${var#pattern}
제거하다가장 짧은 접두사패턴 일치${var##pattern}
제거하다가장 긴 접두사패턴 일치${var%pattern}
제거하다가장 짧은 접미사패턴 일치${var%%pattern}
제거하다가장 긴 접미사패턴 일치
"가장 짧은 것"과 "가장 긴 것"의 차이가 중요합니다. 주어진 문자열 접미사에는 여러 개의 콜론이 포함되어 있습니다. ${tmp%:*}
제거할 때만 사용하십시오.마지막콜론과 그 뒤의 문자입니다.
답변2
perl
PCRE 스타일 정규식 또는 그 변형을 지원하는 경우 grep
직접 일치와 하나 이상의 숫자를 사용하여 값을 선택할 수 있습니다.mode
grep -oP 'mode\s+\K\d+'
나는 당신이 RE를 좋아하지 않는다는 것을 읽었지만 그것은 매우 간단한 패턴이므로 여기서 설명하겠습니다.
- 지금까지의 모든 내용
\K
은 일치해야 하는 역방향 패턴이지만 결과에는 포함되지 않습니다. \s
공백과 일치합니다(보통공간또는상표) 접미사에는+
다음 중 하나 이상이 필요합니다.\d
숫자 접미사(0
..9
)와 일치하려면+
다음 중 하나 이상이 필요합니다.
원하는 값에 숫자가 아닌 텍스트가 포함될 수 있다는 것을 알고 있는 경우 \d+
로 바꿀 수 있습니다. [^:]+
여기서는 [^:]
콜론( )을 :
제외한 모든 항목이 일치됩니다.
인용하다
답변3
간단하고 직접적인 sed
해결책은
sed -n 's/.*mode \([0-9]*\):.*/\1/p'
세 개( ) 대신 단일 명령을 사용하세요 awk | tr | head
. 솔루션이 읽기 쉽다고 생각하시면 도와드릴 수 없습니다.
답변4
나는 이미 제공된 Shell 매개변수 확장 솔루션을 좋아하지만 bash를 사용할 수 없는 경우 다음 AWK 체인이 동일한 방식으로 작동합니다.
... |awk -F"mode " '{print$2}' | awk -F: '{print $1}'
첫 번째 awk 호출은 "mode"에서 문자열을 분할하고 그 뒤에 오는 내용을 반환합니다.
두 번째 호출은 이를 :로 분할하고 이전 내용을 반환합니다.
나에게는 이것이 Bash 매개변수 확장보다 더 읽기 쉽습니다. 그러나 더 장황하고 속도도 느릴 수 있습니다(AWK가 상당히 빠른 것으로 알려져 있지만 두 번 시작하는 오버헤드가 이에 반대됩니다).