일부 줄에 공백이 포함된 경우 목록에서 작동

일부 줄에 공백이 포함된 경우 목록에서 작동

find 명령에서 제외할 디렉토리 목록을 작성하려고 합니다. 불행하게도 이러한 디렉토리 중 일부에는 공백이 있습니다. 예를 들어, myList두 번째 디렉터리가 "bc"인 세 개의 디렉터리 목록이 있다고 가정해 보겠습니다.

/bin/bash
myList="a \\
        b c \\
        d"

두 번째 줄을 두 개의 별도 토큰으로 나누지 않도록 "bash"를 설득할 수 없습니다.

예를 들어, 이 코드는

dirList=
stringArray=($myList)
for i in "${stringArray[@]}" ; do
    dirList="$dirList -name $i -prune -o"
    echo "$dirList"
    echo " "
done

다음을 반환합니다.

-name a -prune -o

 -name a -prune -o -name b -prune -o

 -name a -prune -o -name b -prune -o -name c -prune -o

 -name a -prune -o -name b -prune -o -name c -prune -o -name d -prune -o

하지만 난 그걸 돌려받고 싶어

-name a -prune -o

 -name a -prune -o -name b c -prune -o

 -name a -prune -o -name b c -prune -o -name d -prune -o

공백을 처리하는 확실한 방법은 두 번째 줄을 다음과 같이 정의하는 것입니다. "b c" 그런 다음 중첩된 큰따옴표가 있습니다. 나는 중첩된 따옴표를 처리하는 방법에 대해 웹에서 제안하는 모든 것을 시도했지만 그 중 어느 것도 m에서 효과가 없었습니다. 누구든지 이 작업을 수행하는 방법을 제안할 수 있습니까?

답변1

목록을 문자열로 정의한 다음 배열로 구문 분석하는 대신 처음부터 목록을 배열로 정의하면 어떨까요? 그러면 토큰화되지 않은 방식으로 공백을 처리할 수 있는 큰따옴표로 묶인 문자열 배열을 만들 수 있습니까?

프레이크:

#!/bin/bash
myList=("a" "b c" "d")
dirList=
stringArray=$myList
for i in "${stringArray[@]}" ; do
    dirList="$dirList -name $i -prune -o"
    echo "$dirList"
    echo " "
done

답변2

-name a -prune -o name b c -prune ...실행되는 실제 명령은 단일 문자열이 아니라 여러 문자열이므로 문자열도 필요하지 않습니다 . 단지 를 작성할 때 foo bar "a b"쉘이 따옴표를 해석하고 따옴표가 없는 공백으로 명령줄을 분할하여 3개의 문자열 및 을 제공한다는 것 입니다 foo. 다시 말하지만, 궁극적으로 원하는 것은 매개변수 , 등 입니다 . 문자열이 있으면 문자열을 다른 공백으로 나누기가 어렵지만bara bfind-o-namea b-prune-o -name a b -prune아니요a와 로 나눕니다 b.

먼저, 개별 줄을 끊지 않고 개행으로 구분된 이름 목록을 읽을 수 있는 방법이 필요합니다. Bash를 언급하셨으니 mapfile( readarray) 명령어가 있습니다. 이제 다른 파일에 해당 이름 목록이 있다고 가정해 보겠습니다. 그 다음에,

readarray -t names < listfile

names배열은 파일 내용으로 한 줄에 하나씩 채워집니다.

귀하의 질문에서 문자열에는 myList백슬래시와 두 번째 및 세 번째 디렉토리 앞에 공백도 포함되어 있으므로 목록을 이와 같이 저장하는 경우 정리해야 할 수도 있습니다. 또는 다음과 같이 목록을 배열로 직접 저장할 수도 있습니다.@James S의 답변.


그렇다면 두 번째 문제는 빌드의 매개변수 목록입니다 find. 매개변수를 그대로 유지하고 독립적으로 유지하려면 배열도 필요합니다. 그래서,

args=()
for n in "${names[@]}"; do
    args+=(-name "$n" -prune -o)
done

배열은 매개변수로 채워집니다 args. 그런 다음 다음과 같이 사용할 수 있습니다.

find ... "${args[@]}"

또한 반복할 필요가 없으며 -prune전체를 괄호로 묶고 -prune외부에서 한 번만 사용할 수 있습니다(예: 명령줄에서). ... "(" -name this -o -name that ")" -prune ...다음과 같은 배열을 사용하고 채울 수 있습니다.

args=("(")
for n in "${names[@]}"; do
    args+=(-name "$n" -o)
done
unset "args[${#args[@]} - 1]"  # remove the last -o
args+=( ")" -prune )

바라보다:

답변3

사용하시면 될 것 같아요특수변수 IFS

 #!/bin/bash
OFS=$IFS
IFS=$'\n'

myList="a \\
        b c \\
        d"

dirList=
stringArray=($myList)
for i in "${stringArray[@]}" ; do
    dirList="$dirList -name $i -prune -o"
    echo "$dirList"
    echo " "
done
IFS=$OFS

이것은 주어진 출력입니다:

 -name a \ -prune -o
 
 -name a \ -prune -o -name         b c \ -prune -o
 
 -name a \ -prune -o -name         b c \ -prune -o -name         d -prune -o

관련 정보