내 zsh 쉘 스크립트에서 regexp-replace nname "_{2,}" "_"
여러 개의 "_"를 하나로 성공적으로 줄였지만 zsh를 시도하면 ${nname//_{2,}/'_'}
패턴과 일치하지 않는 것 같습니다.
man zshexpn
예. 확실하지 않다. 여기에는 와일드카드 패턴이 언급되어 있지만 ${name//[^[:alnum:]]/"_"}
내 스크립트에서 제대로 작동하는 것과 같은 다른 POSIX 1003.2 정규식이 있는 것 같습니다 .
동기 부여
다음과 동일한 매개변수 확장을 찾고 있습니다.
regexp-replace nname "[^[:alnum:]]" "_"
regexp-replace nname "_{2,}" "_"
regexp-replace nname "_+$" ""
regexp-replace nname "^_+" ""
다루기 힘든
zsh --version
zsh 5.7.1 (x86_64-apple-darwin19.0)
답변1
${var//pattern/replacement}
zsh 와일드카드 패턴 사용 pattern
(사용된 것과 동일)파일 이름 생성와일드카드라고도 알려져 있으며 sh
와일드카드 패턴의 상위 집합입니다. 구문은 kshglob
및 extendedglob
옵션의 영향도 받습니다. 원래 ${var//pattern/replacement}
Korn 쉘에서 유래되었습니다.
귀하의 경우 extendedglob
이를 활성화하는 것이 좋습니다 . 이는 표준 ERE보다 더 많은 기능을 제공하지만 일부 특수한 경우에는 이전 버전과의 비호환성을 유발할 수 있습니다.set -o extendedglob
~/.zshrc
로그인되어 있는 것을 볼 수 있습니다 info zsh 'filename generation'
.
ERE와 확장 zsh 와일드카드 간의 매핑을 위한 치트 시트:
기준 sh
:
.
->?
.*
->*
[...]
->[...]
zsh 확장자:
*
->#
+
->##
{x,y}
->(#cx,y)
(...|...)
->(...|...)
일부 추가 기능은 표준 ERE에서 사용할 수 없습니다.
^pattern
(부정적인)x~y
(와는 별개로)<12-234>
소수 범위 일치(#i)
대소문자를 구분하지 않는 일치(#a2)
대략적인 일치에서는 최대 2개의 오류가 허용됩니다.- 더 많은 것이 있습니다
와일드카드 패턴이 주제의 시작 부분에 고정되는지 아니면 끝 부분에 고정되는지 여부는 사용되는 연산자에 따라 다릅니다.
- Glob,
case
패턴[[ string = pattern ]]
및${var:#pattern}
모두 고정되어 있습니다( 대신f*.txt
일치함 ).foo.txt
Xfoo.txtY
${var#pattern}
그리고${var##pattern}
처음에 고정됨${var%pattern)
그리고${var%%pattern}
마지막에 고정됨${var/pattern/repl}
고정되어 있지는 않지만${var//pattern/repl}
(시작) 또는 (끝)을 통해 달성할 수 있습니다.${var/#pattern}
${var/%pattern}
(#s)
/ (ERE) 또는 / (PCRE) 와 동등하게 (#e)
사용될 수도 있습니다 .^
$
\A
\z
반복 연산자( #
, ##
, *
, (#cx,y)
, <x-y>
)가 탐욕적인지 여부는 연산자에 따라 다르며( , 에 탐욕 ##
, %%
, 탐욕 //
아님 ) 매개변수 확장 플래그를 통해 변경할 수 있습니다 ./
#
%
S
귀하의 예를 들면 다음과 같습니다.
regexp-replace nname "[^[:alnum:]]" "_"
:${var//[^[:alnum:]]/_}
regexp-replace nname "_{2,}" "_"
:${var//_(#c2,)/_}
regexp-replace nname "_+$" ""
:${var%%_#}
또는${var/%_#}
(여기서는#
동등한 항목을*
사용할 수 있지만 이 경우에는 아무런 차이가 없습니다).##
+
regexp-replace nname "^_+" ""
:${var##_#}
또는${var/#_#}
여기에서 이들을 결합할 수 있습니다 ${${${var//[^[:alnum:]]##/_}#_}%_}
(alnum이 아닌 시퀀스를 변환 _
하고 최종 선행 또는 후행 시퀀스 제거 _
).
_
또 다른 접근 방식은 다음 해킹을 사용하여 모든 alnums 시퀀스를 추출하고 이를 와 결합하는 것입니다 .
words=()
: ${var//(#m)[[:alnum:]]##/${words[1+$#words]::=$MATCH}}
var=${(j:_:)words}
regexp-replace
[[ $var =~ pattern ]]
주기적으로 호출되는 자동 로딩 기능입니다. 참고로 결과는,^
앵커나 단어 경계 또는 뒤보기 연산자(해당 rematchpcre
옵션을 사용하는 경우) 에서는 제대로 작동 하지 않습니다.:
$ a='aaab'; regexp-replace a '^a' x; echo "$a"
xxxb
$ a='abab'; regexp-replace a '\<ab' '<$MATCH>'; echo $a
<ab><ab>
(첫 번째 예에서는 , , 이 루프에서 일치합니다 ^a
.)aaab
aab
ab
b