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 의 출력을 예상대로 구문 분석할 수 없는 이유는 무엇입니까 awk?read

답변1

그것은 관하여대지분할기.

당신은 정의해야기록구분 기호는 각 문자열을 단일 문자열에 넣습니다. 사용 ORS매개변수:

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

그것이 없으면 출력은 다음과 같습니다:

root
root
root
etc...

ALL_TTY_OWNERS_STR변수를 정의할 때그냥 먼저 넣어두세요배열의 첫 번째 요소에 있는 출력 문자열입니다. 따라서 귀하의 배열에는 단 하나의 요소만 포함됩니다. 이는 정확히 귀하가 얻는 것입니다.

답변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 변수를 인용하지 않으면 <<<줄 바꿈은 예상한 공백이 되며 결과는 모두 한 줄에 표시됩니다.

read -r -a ALL_TTY_OWNERS_ARRAY <<< $ALL_TTY_OWNERS_STR

관련 정보