Невозможно проанализировать вывод awk, разделенный пробелами

Вы можете использовать сигнал STOP, чтобы приостановить процесс, и CONT, чтобы возобновить его выполнение:

kill -STOP ${PID}
kill -CONT ${PID}
4
07.09.2017, 10:14
4 ответа

Речь идет о разделителе полей .

Вам необходимо определить разделитель записей , чтобы поместить каждую строку в одну. Используйте ORSпараметр :

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

Без него вывод будет:

root
root
root
etc...

И когда вы определяете ALL_TTY_OWNERS_STRпеременную, вы помещаете только первую строку вывода в первый элемент массива. Из-за этого ваш массив будет содержать только один элемент, и это именно то, что вы получаете

5
27.01.2020, 20:47

Разделителем полей по умолчанию для вывода является пробел. Но разделителем записей является новая строка. ALL_TTY_OWNERS_STRсодержит набор символов 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*) )
4
27.01.2020, 20:47

Если вы не заключите переменную в кавычки после <<<, новые строки станут ожидаемыми пробелами, и результат будет в одной строке:

read -r -a ALL_TTY_OWNERS_ARRAY <<< $ALL_TTY_OWNERS_STR
0
27.01.2020, 20:47

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}')

Или вы можете использовать оператор 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*

(что было бы полезно также работать с именами пользователей, содержащими пробелы ).

3
27.01.2020, 20:47

Теги

Похожие вопросы