경로가 포함된 일부 문자열을 처리해야 합니다. /
이러한 문자열을 구분 기호로 분할하여 알 수 없는 경로 부분 수를 생성하는 방법 과 궁극적으로 결과 경로 부분을 추출하는 방법은 무엇입니까?
cut
분명히 부품 수를 미리 알아야 하고 각 부품을 출력하여 사용하거나 readarray
배열 mapfile
로 수집할 수 없기 때문에 선택하는 도구는 아닙니다.
답변1
에서 bash
단일 문자 구분 기호의 경우 glob 부분을 비활성화한 후 분할+glob 연산자를 사용할 수 있습니다(목록 컨텍스트에서 따옴표가 없는 확장 유지).
string='foo/bar
baz/asd..'
IFS=/
set -o noglob
array=( $string )
와 string='/foo/'
로만 분할된다는 점에 유의하세요 (분할할 때와 동일) . , 및 으로 분할하려면 다음을 수행할 수 있습니다.""
"foo"
string='/foo'
""
"foo"
""
IFS=/
set -o noglob
array=( $string'' )
그래도 string=''
0 요소 대신 빈 요소로 분할됩니다.
( zsh
split+glob은 /emulation을 제외하고 따옴표가 없는 확장을 수행하지 않음)에서는 단일 문자 구분 기호로 제한되지 않는 매개변수 확장 플래그를 사용할 수 있습니다.sh
ksh
s
array=( ${(s[/])string} )
빈 요소를 제거하거나 다음을 수행합니다.
array=( "${(@s[/])string}" )
빈 요소는 유지됩니다. /foo/
그런 다음 이를 로 분할 ""
하고 빈 문자열을 0개 요소로 분할합니다 "foo"
.""
변수에 저장된 구분 기호를 사용하여 분할할 수 있습니다.
array=( "${(@ps[$delimiter])string}" )
이 p
플래그를 사용하면 이스케이프 시퀀스(예: , )를 입력할 수도 있습니다 \0
. 이 두 플래그에는 개행에서 분할, NUL에서 분할( 예: , ...의 출력을 분할하는 데 사용할 수 있음 ) \n
이라는 단축 플래그가 있습니다 .f
0
find -print0
grep -lZ
sort -z
files=( ${(0)"$(grep -lZ pattern -- *)"} )
에서는 zsh
다음을 수행할 수도 있습니다.묶다주어진 단일 바이트를 구분 기호로 사용하여 배열 변수를 스칼라 변수로 변환합니다. $path
in 은 zsh
실제로 이런 방식으로 구분 기호로 묶인 특수 배열입니다 $PATH
( :
에서 영감을 얻음 csh
). 어떤 변수로도 이 작업을 수행할 수 있습니다. 예를 들면 다음과 같습니다.
typeset -T string array /
배열 과 /
연결 - 분리.$string
$array
답변2
Bash에서는 read -a
here-string을 사용하여 문자열을 배열로 분할할 수 있습니다.
path=/foo/bar/doo
IFS=/ read -r -a parts <<< "$path"
foo
이렇게 하면 4개의 요소(비어 있음) , bar
및 가 있는 배열이 제공됩니다 doo
.
read
개행 문자는 기본적으로 구분 기호로 처리되므로 개행 문자가 포함된 경로에는 작동하지 않습니다 . 이를 방지하려면 를 추가해야 -d ''
하지만 문제가 있습니다. 여기서 문자열은 개행 문자를 추가한 다음 마지막 요소에서 제거해야 합니다.
path=$'/path/with/new\nlines'
IFS=/ read -d '' -r -a parts <<< "$path"
parts[-1]=${parts[-1]%$'\n'}
( parts[-1]
배열의 마지막 요소를 나타내고 일치하는 후행 ${var%text}
값을 제거하도록 확장됩니다.)var
text
또한 경로에 반복되는 슬래시가 포함될 수 있는 경우(예: ) foo//bar
, 중간에 빈 배열 요소가 표시됩니다. 마찬가지로 경로가 슬래시로 끝나면 끝에 빈 요소가 표시됩니다.
이를 무시하거나 경로를 전처리하여 제거할 수 있습니다. 이와 같은 방법을 사용하여 중복 슬래시를 제거할 수 있습니다.
shopt -s extglob
path="${path//+('/')/'/'}"
후행 슬래시를 제거하십시오.
shopt -s extglob
path="${path%+('/')}"
//foo
그러나 이중 슬래시 는 단일(또는 삼중 등) 슬래시와 달리 경로 이름 시작 부분에
답변3
readarray
...각 섹션을 출력하지 않고 다음을 사용할 수 있습니다.mapfile
mapfile/readarray를 사용하여 전체 문자열을 제공하고 구분 기호를 설정하세요. 예를 들어,
str='/f
oo/bar/'
mapfile -d / arr < <(printf '%s' "$str")
declare -p arr
산출:
declare -a arr=([0]="/" [1]=$'f\noo/' [2]="bar/")