私は簡単なことをしたいのですが、ここで私の目標を達成する方法がわかりません。
w
コンソールからコマンドで指定されたUSER、TTY、FROM値を抽出しようとしています。 Bashはこの出力を取得し、値を多次元配列(またはスペース区切り記号付きの配列)に入れようとします。
#!/bin/bash
w|awk '{if(NR > 2) print $1,$2,$3}' | while read line
do
USERS+=("$line")
echo ${#USERS[@]}
done
echo ${#USERS[@]}
単一の配列から値を行単位で読み取る方法を見つけましたが、USERS配列の値をwhileループの範囲外に移動することはできないようです。ループ後、1、2、3、4の値を印刷してから0を印刷します。私が読んだすべての例は範囲外の変数をうまく利用していますが、それはできないようです。
ベストアンサー1
主な問題は、パイプラインの最後のコマンドがパイプラインの他のすべてのコマンドと同様にサブシェルで実行されることです。これはほとんどの殻の場合です。 ATT ksh と zsh は例外です。それらは親シェルでパイプラインの最後のコマンドを実行します。
Bash 4.2以降の設定では、bashにkshやzshのように動作するように指示できます。lastpipe
オプション。
#!/bin/bash
USERS=()
shopt -s lastpipe
w | awk '{if(NR > 2) print $1,$2,$3}' | while read line; do
USERS+=("$line")
done
echo ${#USERS[@]}
または、次のものを使用できます。プロセスの交換パイプの代わりにread
コマンドがデフォルトのシェルプロセスで実行されるようにします。
#!/bin/bash
USERS=()
while read line; do
USERS+=("$line")
done < <(w | awk '{if(NR > 2) print $1,$2,$3}')
echo ${#USERS[@]}
あるいは、Bourne、dash、pdkshなど、プロセスの置き換えやksh / zshの動作なしでシェルで動作する移植可能なアプローチを使用できます。 (配列の場合はまだ(pd)ksh、bash、またはzshが必要です。)パイプ内のデータが必要なすべてはパイプ内で実行されます。
#!/bin/bash
USERS=()
shopt -s lastpipe
w | awk '{if(NR > 2) print $1,$2,$3}' | {
while read line; do
USERS+=("$line")
done
echo ${#USERS[@]}
}