
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"
(何らかの理由で使用しているルートを破るために脱出を無効にしました。)