공백이 포함된 구성된 문자열 목록에서 선택하시겠습니까?

공백이 포함된 구성된 문자열 목록에서 선택하시겠습니까?

select다음과 같이 선택하려는 공백이 포함된 문자열 목록을 만들려고 합니다 .

sel=""
while read l   
do
  sel=$(printf "%s '%s'" "$sel" "$l")
done< <(cd /some/data/directory;du -sh *) 

select x in $sel
do
  break
done

문자열은 sel예상: 과 유사 "597G 2022" "49G analysis" "25K @Recycle"하지만 선택 항목은 다음과 같습니다.

1) "597G      3) "49G       5) "25K
2) 2022"      4) analysis"  6) @Recycle"
#?

내가 달성하고 싶은 것은 물론입니다.

1) 597G 2022
2) 49G  analysis
3) 25K  @Recycle
#?

보다 일반적으로는 여러 데이터 소스에서 어떤 방식으로든 구성된 문자열 중에서 선택할 수 있습니다. 나는 다음과 같은 몇몇 곳에서 영감을 찾습니다.여기, 하지만 내 경우에는 맞지 않습니다.

편집하다

이 bash는 꽤 오래되었다는 점을 언급하는 것을 잊어버렸습니다(슬프게도 업데이트할 수 없습니다).

[admin@CoMind-UniCron ~]# bash --version
GNU bash, version 3.2.57(1)-release (x86_64-QNAP-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.

답변1

쉘에 의해 적절하게 분할되어야 하는 단일 문자열이 아닌 여러 문자열의 배열이 필요합니다. 이 같은:

#!/bin/bash

while read l   
do
  sel+=( "$l" )
done< <(cd /some/data/directory;du -sh *) 

select x in "${sel[@]}"
do
  break
done

그러면 예상되는 출력이 생성됩니다.

$ foo.sh
1) 597G 2022
2) 50G  analysis
3) 32K  @Recycle
#? 

줄 바꿈을 제외한 임의의 파일/디렉토리 이름을 처리할 수 있고 약간 더 복잡하지만 모든 경우에 걱정 없이 사용할 수 있는 더 안전한 방법입니다.

#!/bin/bash

while IFS= read -r l   
do
  sel+=( "$l" )
done< <(shopt -s nullglob dotglob; cd /some/data/directory && du -sh -- *) 

select x in "${sel[@]}"
do
  break
done

답변2

이건 정말 생각할 거리가 너무 많아요.

#!/usr/bin/env bash

IFS='
'
select x in $(cd /some/data/directory && du -sh -- *); do
    break
done
unset IFS  # or save/restore it explicitly

추가 보너스로 여기서 유일한 공격은 select.

타이프스크립트:

$ ./cg
 1) 0   0
 2) 0   000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 3) 0   000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 4) 0   000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a
 5) 0   000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ą
 6) 60k 1028501896.pdf
 7) 0   a
 8) 16k a.bkp
 9) 36k a.cpio
10) 10k a.d
11) 36k a.patch
12) 60k a.pax
13) 84k a.png
14) 4k  b.cpio
15) 32k b.pax
16) 12k b.tar
17) 0   bugreport.cgi?bug=910770;mbox=yes;mboxmaint=yes
18) 74.2M       build-output
19) 796k        busybox
20) 428k        busybox_1%3a1.30.1-6+b3_amd64.deb
21) 0   CB_Unix
22) 4k  cg
#? 

인용 제거는 원래 단어에서만 작동하므로 매개변수 확장의 결과는 단지 필드 분할(및 와일드카드)이기 때문입니다. 이렇게 하려면 문자열을 입력으로 표시해야 합니다.

eval "select x in $sel
do
  break
done"

명백한 이유로 실제로 파일 이름을 이스케이프하지 않았으므로 이 작업을 수행해서는 안 됩니다.

$ ./cg
./cg: eval: line 11: unexpected EOF while looking for matching `''
./cg: eval: line 15: syntax error: unexpected end of file

만약 너라면진짜각 행마다 프로세스를 분기해야 하며진짜du 출력을 큰 문자열로 저장해야 한다면 이렇게 해야 합니다.

#!/usr/bin/env bash

sel=
while read -r l; do
    sel="$(printf '%s %q' "$sel" "$l")"
done < <(cd /some/data/directory && du -sh -- *) 

eval "select x in $sel; do
  break
done"

(어떤 이유로든 사용하고 있는 경로를 깨기 위해 탈출을 비활성화했습니다.)

관련 정보