Bash: 검색에서 주어진 패턴의 마지막 항목 바꾸기 및 바꾸기

Bash: 검색에서 주어진 패턴의 마지막 항목 바꾸기 및 바꾸기

이것배쉬 해커 위키설명하다

${PARAMETER/PATTERN/STRING}

${PARAMETER//PATTERN/STRING}

This one can substitute (replace) a substring matched by a
pattern, on expansion time. The matched substring will be entirely
removed and the given string will be inserted.

The first one (one slash) is to only substitute the first
occurrence of the given pattern, the second one (two slashes) is
to substitute all occurrences of the pattern.

array[@]이 접근 방식은 구문을 사용하여 Bash 배열에서도 작동합니다 . 하지만 누군가가 특정 패턴의 마지막 발생을 대체하고 싶어한다고 가정해 보겠습니다. Bash는 분명히 이를 수행하는 방법을 제공하지 않습니다.

이는 단일 문자열과 일반 문자열인 패턴에 대해 수행할 수 있습니다(예:https://unix.stackexchange.com/a/187920/4671)

s=/foo/bar/baz
echo ${s%/*}/prefix-${s##*/}

이것은 만든다

/foo/bar/prefix-baz

그러나 이것은 배열에서는 작동하지 않습니다. 그러나 다음과 같이 배열에 대해 명시적인 루프를 작성하는 것이 가능합니다.

a=(foo/bar/baz foo/bar/boo)
b=()
for i in "${a[@]}"; do
    b+=("${i%/*}/prefix-${i##*/}")
done
echo "${b[@]}"

이것은 만든다

foo/bar/prefix-baz foo/bar/prefix-boo

그래서 두 가지 관련 질문이 있습니다.

  1. Bash가 마지막 일치 항목을 바꾸는 옵션을 제공하지 않는 이유는 무엇입니까? 이것은 구현되지 않은 기능인가요? 아니면 구현할 수 없는 기술적인 이유가 있나요? 왜냐하면 이것은 이상한 공백처럼 보이기 때문입니다. 다른 쉘과의 비교를 환영합니다.

  2. 배열을 반복하지 않고 마지막 일치 항목을 바꾸는 방법이 있습니까? 분명히 Zsh는 전문가가 사용하는 것이므로 원하는 경우 Zsh 솔루션을 자유롭게 제공하십시오.

답변1

나는 그것이 존재한다고 확신하지만, 그 기능을 가진 어떤 언어의 연산자도 모릅니다. seds 를 보면 n번째 항목을s/../../바꿀 수 있지만 마지막 항목부터 시작하는 항목 수는 바꿀 수 없습니다.s/../../n

나는 그것이 기능을 너무 모호하게 만드는 것 같아요.

ksh여기에서 ' 및 역참조를 사용할 수 있습니다 ${var/pattern/replacement}.

그리고 zsh:

set -o extendedglob
b=("${a[@]/%(#m)[^\/]#/prefix-$MATCH}")

( (#m)쌍의 일치하는 부분 캡처가 활성화되는 경우 $MATCH)

또는:

b=("${(S)a[@]/%(#b)\/(*)//prefix-$match[1]}")

( (#b)역참조를 활성화하여 그룹의 일치하는 부분을 (...)배열의 요소로 캡처하고 일치 항목을 덜 탐욕스럽게 $match만듭니다 ).S

그리고 ksh93:

b=("${a[@]/%*([^\/])/prefix-\1}")

에서는 zsh다음 작업도 수행할 수 있습니다.

dirs=($a:h)
new_bases=(prefix-$^a:t)
b=()
printf -v b %s/%s ${dirs:^new_bases}

관련 정보