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"
(어떤 이유로든 사용하고 있는 경로를 깨기 위해 탈출을 비활성화했습니다.)