私が正しく理解していれば、awk
の出力のデフォルトの区切り文字は スペース です。
ただし、次のスクリプトは期待どおりに動作しません。 awk
の出力を配列に解析することができません。
#!/bin/bash
echo "------ with input string from awk ------"
ALL_TTY_OWNERS_STR=$(ls -l /dev | grep tty | awk '{print $3}')
read -r -a ALL_TTY_OWNERS_ARRAY <<< "$ALL_TTY_OWNERS_STR"
echo "${#ALL_TTY_OWNERS_ARRAY[@]}" # This says 1
echo "${ALL_TTY_OWNERS_ARRAY[0]}" # "root", as expected
echo "${ALL_TTY_OWNERS_ARRAY[1]}" # empty string, expected "root"
echo "${ALL_TTY_OWNERS_ARRAY[2]}" # empty string, expected "root"
echo "------ with my manually created input string ------"
ALL_TTY_OWNERS_STR="root root root" # only for testing
read -r -a ALL_TTY_OWNERS_ARRAY <<< "$ALL_TTY_OWNERS_STR"
echo "${#ALL_TTY_OWNERS_ARRAY[@]}" # 3, as expected
echo "${ALL_TTY_OWNERS_ARRAY[0]}" # "root", as expected
echo "${ALL_TTY_OWNERS_ARRAY[1]}" # "root", as expected
echo "${ALL_TTY_OWNERS_ARRAY[2]}" # "root", as expected
awk
の出力をread
で解析できないのはなぜですか?
それは約フィールドセパレーターです。
各文字列を1つにまとめるには、recordセパレータを定義する必要があります。 ORS
paramを使用します:
ls -l /dev | grep tty | awk 'BEGIN { ORS=" " }; {print $3}'
それがないと、次のように出力されます。
root
root
root
etc...
そして、ALL_TTY_OWNERS_STR
変数を定義すると、最初にのみ置く配列の最初の要素の出力の文字列。このため、配列には1つの要素のみが含まれ、これがまさにあなたが得ているものです。
出力のデフォルトのフィールド区切り文字はスペースです。ただし、レコード区切り文字は改行です。 ALL_TTY_OWNERS_STR
には、改行で区切られたroot
sの束が含まれています。
$ printf "%q\n" "$ALL_TTY_OWNERS_STR"
$'root\nroot\nroot\n....
そして、read
はデフォルトで、最初の改行まで読み取ります。
ALL_TTY_OWNERS_ARRAY
のすべてのユーザーが必要な場合は、次のようにする方が簡単な場合があります。
ALL_TTY_OWNERS_ARRAY=( $(stat -c '%U' /dev/*tty*) )
read -a array
は、1つのレコードからすべての単語をarray
に読み込みます。
入力全体からすべての単語を読み取りたい場合は、入力で発生しないレコード区切り文字を使用します。たとえば、レコード区切り文字としてNUL文字を使用する-d ''
、または-d :
( :
はユーザー名では使用できません)。
IFS=$'\n' read -rd '' -a array < <(ls -Ll /dev | awk '/tty/{print $3}')
(ここでは-L
を使用して、シンボリックリンクの場合、シンボリックリンクではなくデバイスの所有権が返されるようにします)。
または、配列に格納される入力のlineごとにreadarray
を使用します。
readarray -t array < <(ls -Ll /dev | awk '/tty/{print $3}')
または、split + glob演算子を使用できます。
set -o noglob # disable glob part
IFS=$'\n' # split on newline
array=($(ls -Ll /dev | awk '/tty/{print $3}')) # invoke split+glob by leaving
# the $(...) unquoted.
tty
はls -Ll
の出力全体で検索されるため、ユーザー名とグループ名、ファイル名(および、-L
を省略した場合はシンボリックリンクのターゲット)が含まれることに注意してください。ファイル名のみを検討したい場合は、次のことができます。
ls -Lld /dev/*tty* | awk '{print $3}'
代わりに。
zsh
を使用すると、次のことができます。
zmodload zsh/stat
stat -s -A array +uid /dev/*tty*
(これには、空白を含むユーザー名に対しても機能するという利点があります)。
<<<
の後に変数を引用符で囲まない場合、改行は期待する空白になり、結果はすべて1行になります。
read -r -a ALL_TTY_OWNERS_ARRAY <<< $ALL_TTY_OWNERS_STR