将命令输出拆分为行数组

时间:2016-05-25 03:43:43

标签: bash

这是我的bash函数,用于获取命令输出作为参数,然后返回输出行数组。

function get_lines { 
    while read -r line; do 
        echo $line
    done <<< $1
}

SESSIONS=`loginctl list-sessions`
get_lines "$SESSIONS"

loginctl list-sessions的实际输出为:

   SESSION        UID USER             SEAT            
        c2       1000 asif             seat0           
        c7       1002 sadia            seat0           

但是while循环仅在一行打印所有输出时运行。如何获得一系列行并将其返回?

3 个答案:

答案 0 :(得分:2)

您可以使用readarray并避免使用get_lines函数:

readarray SESSIONS < <(loginctl --no-legend list-sessions)

这将创建数组SESSIONS,并将命令输出的每一行映射到数组的元素。

答案 1 :(得分:1)

这个答案的价值在于解释OP代码的问题   - 其他答案显示使用 Bash v4 + 内置mapfile(或其有效别名,readarray)来直接读取数组元素中的输入,而不是需要自定义shell功能。
  - 在 Bash v3.x 中,您可以使用IFS=$'\n' read -r -d '' -a lines < <(...),,但请注意,将忽略空行。

您的主要问题是未加引号(非双引号)使用$1会使shell将word-splitting应用于其内容,从而有效地规范化所有空白行 - 包括换行符 - 每个单独的空格,导致while循环的输入行。

其次,使用$input取消加引号会在echo的输出上再次应用此分词。

最后,使用read而不设置$IFS,内部字段分隔符,空字符串 - 通过IFS= read -r line - 从每个输入行修剪前导和尾随空格。

也就是说,你可以简化你的函数直接从stdin读取而不是参数:

function get_lines { 
    while IFS= read -r line; do 
        printf '%s\n' "$line"
    done
}

然后您可以使用process substitution

按如下方式调用
get_lines < <(loginctl list-sessions)

使用管道也可以,但get_lines将在子shell 中运行,这意味着它无法设置当前可见的变量壳:

loginctl list-sessions | get_lines

答案 2 :(得分:1)

这是bash v4 +中的一种方式:

SESSIONS=`loginctl list-sessions`
mapfile -t myArray <<< "$SESSIONS"

REF:

Creating an array from a text file in BASH with mapfile