
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"
답변1
ksh93
가 아닌 내부에서 zsh
역참조(또는 더 정확하게는 1 , 대체 캡처 그룹에 대한 참조)를 지원 합니다 .${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
이를 지원할 것이라고 언급되어 있습니다 . 2017-04-25 현재로서는 아직 사용할 수 없습니다.)${KSH_MATCH[1]}
그러나 를 사용하면 다음을 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 ]]
ERE를 사용합니다.
[[ aa =~ (.)\1 ]]
어울리지는 않겠지만
re='(.)\1'; [[ aa =~ $re ]]
시스템의 ERE가 지원하는 경우 가능합니다.
답변2
␣->␣
첫 번째 ("화살표" 제외)와 마지막 이후 ␣/
(공백 및 슬래시 포함) 까지 모든 내용을 삭제하려고 합니다 .
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
.
답변3
정확한 형식을 모르면 이에 대해 확실히 대답하는 것은 불가능합니다.모든메시지가 걸립니다. 그러나 일반적인 접근 방식으로 다음을 사용하여 특정 특정 필드를 인쇄할 수 있습니다 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