내가 이것을 가지고 있다고 가정 해 봅시다 :
str="@test/string"
echo $str
@test/string
echo ${str#@}
test/string
예상대로 작동하지만
echo ${str//\//-}
ksh: ${str//\//-}: bad substitution
실패하다. (@test-string 예상)
이와 같은 문자를 바꾸거나 바꾸는 올바른 방법은 무엇입니까?
echo $KSH_VERSION
KSH version @(#)PD KSH v5.2.14 99/07/13.2
답변1
예 ${var//pattern/replacement}
는 ksh93 연산자인 반면 pdksh는 마지막 버전인 ksh88i1인 원본 ksh의 복제본으로 사용됩니다. pdksh는 프로젝트로서 중단되었지만 sh
OpenBSD 및 MirBSD를 포함한 소수의 BSD의 일부로 여전히 존재합니다. mksh라고도 알려진 MirBSD sh/ksh는 휴대용 셸로도 유지 관리되며 많은 Linux 배포판(Android에서도 가능 sh
)에서 사용할 수 있습니다. 2008 R33 릴리스에는 ksh93 연산자가 추가되었습니다.
POSIXly에서는 변수의 한 문자를 다른 문자로 바꾸려면 tr
ansliterator 유틸리티를 사용할 수 있지만 stdin에서 변수의 내용을 제공하고 stdout에서 결과를 가져와야 합니다.
newstr=$(printf %s "$str" | tr / -; echo .)
newstr=${newstr%.}
.\n
(이는 명령 대체가 후행 줄 바꿈을 제거한다는 사실을 설명하기 위해 추가되었습니다 ).
별도의 명령을 실행하지 않으려면 분할+glob 연산자를 사용할 수도 있습니다.
IFS=/ # split on /
set -o noglob # disable the glob part
set -- $str'' # split+glob by leaving $str unquoted
IFS=. # join on . in "$*"
newstr="$*"
1 ksh93은 이전 버전과 완전히 호환되지는 않지만 많은 새로운 기능을 가지고 있는 재작성이지만, 그 중 많은 기능은 여전히 실험적이며 2000년대에 코드가 오픈 소스로 출시되기 전에는 거의 사용되지 않았습니다.
답변2
쉘은 pdksh
언급한 비표준 매개변수 대체 없이 OpenBSD와 같은 새로운 사용자를 위한 기본 쉘입니다.
일부 패턴과 겹치지 않는 모든 일치 항목을 새 문자열로 바꾸려면 다음을 사용할 수 있습니다 sed
.
str=$( printf '%s\n' "$str" | sed 's/PATTERN/REPLACEMENT/g' )
PATTERN
이는 POSIX 기본 정규식 으로 사용되며 특별한 방법으로 해석되는 다른 문자열뿐만 아니라 이스케이프 REPLACEMENT
되어야 하며 명령 대체는 문자열 끝에서 후행 개행 문자를 제거합니다.&
\1
sed
예:
$ str=@title/section1/section2
$ str=$( printf '%s\n' "$str" | sed 's/\//-/g' )
$ printf '%s\n' "$str"
@title-section1-section2
이 경우 문자 하나만 바꿀 경우 sed
로 바꾸 y/\//-/
거나, sed
전체 명령을 tr
command 로 바꾸면 됩니다 tr / -
.
쉘 루프를 작성할 수도 있습니다:
while true; do
case $str in
*PATTERN*)
str=${str%%PATTERN*}REPLACEMENT${str#*PATTERN}
;;
*)
break
esac
done
이 코드에는 PATTERN
셸 패턴("파일 이름 글로빙 패턴")이 있습니다. 코드는 더 이상 일치하는 항목이 없을 때까지 문자열에서 처음 나타나는 패턴을 대체 문자열로 반복적으로 바꿉니다. 루프의 존재로 인해 후속 반복에서 이전에 삽입된 대체 문자열에서 대체를 수행하지 않는다는 보장이 없습니다.
예:
$ str=@title/section1/section2
$ while true; do case $str in (*/*) str=${str%%/*}-${str#*/} ;; (*) break; esac; done
$ printf '%s\n' "$str"
@title-section1-section2
답변3
확실히 더 좋은 방법이지만:
$(echo "$str" | tr '/' '-')