나는라는 변수가 descr
문자열을 포함 할 수 있습니다 Blah: -> r1-ae0-2 / [123]
, -> s7-Gi0-0-1:1-US / Foo
등 내가 싶어 -> r1-ae0-2
, -> s7-Gi0-0-1:1-US
문자열에서 일부를. 현재 나는 이것을 위해 사용 descr=$(grep -oP '\->\s*\S+' <<< "$descr"
합니다. 더 좋은 방법이 있습니까? 매개 변수 확장으로이 작업을 수행 할 수도 있습니까?
답변
ksh93
및 zsh
백 레퍼런스 (또는보다 정확하게이 하나 의 여분의 포획 기 참조) 지지체 내부는 ${var/pattern/replacement}
,하지 bash
.
ksh93
:
$ var='Blah: -> r1-ae0-2 / [123]'
$ printf '%s\n' "${var/*@(->*([[:space:]])+([^[:space:]]))*/\1}"
-> r1-ae0-2
zsh
:
$ var='Blah: -> r1-ae0-2 / [123]'
$ set -o extendedglob
$ printf '%s\n' "${var/(#b)*(->[[:space:]]#[^[:space:]]##)*/$match[1]}"
-> r1-ae0-2
( mksh
man 페이지는 또한 향후 버전이 ${KSH_MATCH[1]}
첫 번째 캡처 그룹 을 위해 이를 지원할 것이라고 언급하고 있습니다 ( 2017-04-25 기준).
그러나을 사용 bash
하면 다음을 수행 할 수 있습니다.
$ [[ $var =~ -\>[[:space:]]*[^[:space:]]+ ]] &&
printf '%s\n' "${BASH_REMATCH[0]}"
-> r1-ae0-2
패턴이 먼저 발견되는지 확인하는 것이 좋습니다.
시스템의 정규 표현식이 \s
/를 지원하는 경우 다음 \S
을 수행 할 수도 있습니다.
re='->\s*\S+'
[[ $var =~ $re ]]
을 사용 zsh
하면 다음을 통해 PCRE의 모든 기능을 활용할 수 있습니다.
$ set -o rematchpcre
$ [[ $var =~ '->\s*\S+' ]] && printf '%s\n' $MATCH
-> r1-ae0-2
로 다음 zsh -o extendedglob
을 참조하십시오.
$ printf '%s\n' ${(SM)var##-\>[[:space:]]#[^[:space:]]##}
-> r1-ae0-2
포터블 :
$ expr " $var" : '.*\(->[[:space:]]*[^[:space:]]\{1,\}\)'
-> r1-ae0-2
문자열에 패턴이 여러 번 나타나는 경우 모든 솔루션에 따라 동작이 달라집니다. 그러나 그중 어느 것도 GNU grep
기반 솔루션 에서와 같이 줄 바꿈으로 구분 된 모든 일치 목록을 제공하지 않습니다 .
그렇게하려면 손으로 루핑을해야합니다. 예를 들어,에 bash
:
re='(->\s*\S+)(.*)'
while [[ $var =~ $re ]]; do
printf '%s\n' "${BASH_REMATCH[1]}"
var=${BASH_REMATCH[2]}
done
을 사용하면 zsh
모든 일치 항목을 배열에 저장하는 이러한 종류의 트릭을 사용할 수 있습니다.
set -o extendedglob
matches=() n=0
: ${var//(#m)->[[:space:]]#[^[:space:]]##/${matches[++n]::=$MATCH}}
printf '%s\n' $matches
1 역 참조는 이전 그룹과 일치하는 것을 참조하는 패턴을 더 일반적으로 지정합니다. 예를 들어, \(.\)\1
기본 정규 표현식은 단일 문자 다음에 동일한 문자가옵니다 (on aa
이 아니라 on ab
). 이는 동일한 패턴 \1
으로 해당 \(.\)
캡처 그룹에 대한 역 참조 입니다.
ksh93
ls -d -- @(?)\1
다른 셸이 아닌 패턴에서 역 참조를 지원합니다 (예 : 두 개의 동일한 문자로 구성된 파일 이름을 나열 함). 표준 BRE 및 PCRE는 역 참조를 지원하지만 표준 ERE는 지원하지 않지만 일부 ERE 구현에서는이를 확장으로 지원합니다. bash
의 [[ foo =~ re ]]
사용의 ERES을.
[[ aa =~ (.)\1 ]]
일치하지 않지만
re='(.)\1'; [[ aa =~ $re ]]
시스템의 ERE가이를 지원한다면
답변
첫 번째 ␣->␣
( “화살표”제외) 및 마지막 ␣/
(공백 및 슬래시 포함 ) 까지 모든 항목을 삭제하려고합니다 .
string="Blah: -> r1-ae0-2 / [123]"
string=${string/*->/->}
string=${string/ \/*}
$string
이제 것 -> r1-ae0-2
입니다.
같은 두 개의 대체가 될지는 -> s7-Gi0-0-1:1-US / Foo
으로 -> s7-Gi0-0-1:1-US
.
답변
모든 메시지 의 정확한 형식을 모른 채 확실하게 대답하는 것은 불가능 합니다. 그러나 일반적인 방법으로 다음을 사용하여 특정 필드를 인쇄 할 수 있습니다 cut
.
$ cut -d ' ' -f 2 <<< '-> s7-Gi0-0-1:1-US / Foo'
s7-Gi0-0-1:1-US
또는 다음을 사용하여 모든 n 번째 열을 인쇄awk
할 수 있습니다 .
$ awk -F' ' '{ for (i=2;i<=NF;i+=4) print $i }' <<< '-> r1-ae0-2 / [123], -> s7-Gi0-0-1:1-US / Foo'
r1-ae0-2
s7-Gi0-0-1:1-US