bash는 매개변수 확장 시 역참조를 지원합니까?

bash는 매개변수 확장 시 역참조를 지원합니까?

descr문자열 등을 포함할 수 있는 변수가 있습니다 Blah: -> r1-ae0-2 / [123]. 문자열에서 부분을 가져 -> s7-Gi0-0-1:1-US / Foo오고 싶습니다 . 현재 나는 이것을 위해 사용합니다. 이를 수행하는 더 좋은 방법이 있습니까? 매개변수 확장을 통해서도 가능합니까?-> r1-ae0-2-> s7-Gi0-0-1:1-USdescr=$(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

관련 정보