awkのスペースで区切られた出力を解析できません。

awkのスペースで区切られた出力を解析できません。

正しく理解した場合、出力のデフォルトの区切り記号は次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

withの出力を期待どおりに解析できないのはなぜですかawkread

答え1

それについて大地スプリッタ。

あなたは定義する必要があります記録区切り文字は、各文字列を単一の文字列に入れます。使用ORSパラメータ:

ls -l /dev | grep tty | awk 'BEGIN { ORS=" " }; {print $3}'

それがなければ、出力は次のようになります。

root
root
root
etc...

ALL_TTY_OWNERS_STR変数を定義するときただ最初に入れてください。配列の最初の要素の出力文字列です。したがって、あなたの配列には1つの要素しか含まれません。これはまさにあなたが得るものです。

答え2

出力のデフォルトのフィールド区切り文字は空白です。ただし、レコード区切り文字は新しい行です。改行で区切られたALL_TTY_OWNERS_STR複数のsを含みます。root

$ 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*) )

答え3

read -a arrayレコードのすべての単語を読みますarray

入力全体のすべての単語を読み取るには、-d ''NUL文字をレコード区切り文字として使用するか、入力に表示されないレコード区切り文字を使用してください(ユーザー名には表示できません)-d ::

IFS=$'\n' read -rd '' -a array < <(ls -Ll /dev | awk '/tty/{print $3}')

(ここではシンボリックリンクが使用され、-Lシンボリックリンクではなくデバイスの所有権を返します。)

またはreadarrayそれぞれについてワイヤー配列に保存される入力です。

readarray -t array < <(ls -Ll /dev | awk '/tty/{print $3}')

または、分割+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*

(これはスペースを含むユーザー名にも役立ちます。)

答え4

after変数を引用しないと、<<<改行は予想される空白になり、結果はすべて1行に表示されます。

read -r -a ALL_TTY_OWNERS_ARRAY <<< $ALL_TTY_OWNERS_STR

関連情報