如何在Bash中逐个添加多行输出?

时间:2014-05-01 11:48:19

标签: bash shell awk

这可能是一个非常基本的问题,但我无法找到解决方案。我有一个脚本:

如果我在服务器的命令行中运行w | awk '{print $1}',我会得到:

f931
smk591
sc271
bx972
gaw844
mbihk988
laid640
smk59
ycc951

现在我需要逐个在我的bash脚本中使用这个列表,并对它们进行一些操作。我需要检查他们的小组并打印出特定的小组。检查其组的命令是id username。如何保存它们或逐个循环遍历它们。

到目前为止我所拥有的是

tmp=$(w | awk '{print $1})

但它只返回第一个记录!感谢任何帮助。

5 个答案:

答案 0 :(得分:3)

使用命令的输出填充数组:

$ tmp=( $(printf "a\nb\nc\n") )
$ echo "${tmp[0]}"
a
$ echo "${tmp[1]}"
b
$ echo "${tmp[2]}"
c

printf替换为您的命令(例如tmp=( $(w | awk '{print $1}') ))和man bash,了解如何使用bash数组。

更长,更健壮,更完整的例子:

$ cat ./tstarrays.sh
# saving multi-line awk output in a bash array, one element per line
# See http://www.thegeekstuff.com/2010/06/bash-array-tutorial/ for
# more operations you can perform on an array and its elements.

oSET="$-"; set -f       # save original set flags and turn off globbing
oIFS="$IFS"; IFS=$'\n'  # save original IFS and make IFS a newline

array=( $(
    awk 'BEGIN{
        print "the      quick   brown"
        print "    fox jumped\tover\tthe"
        print "lazy    dogs back    "
    }'
) )

IFS="$oIFS"             # restore original IFS value
set +f -$oSET           # restore original set flags

for (( i=0; i < ${#array[@]}; i++ ));
do
    printf "array[%d] of length=%d: \"%s\"\n" "$i" "${#array[$i]}" "${array[$i]}"
done

printf -- "----------\n"
printf -- "array[@]=\n\"%s\"\n" "${array[@]}"

printf -- "----------\n"
printf -- "array[*]=\n\"%s\"\n" "${array[*]}"

$ ./tstarrays.sh
array[0] of length=22: "the      quick   brown"
array[1] of length=23: "    fox jumped  over    the"
array[2] of length=21: "lazy    dogs back    "
----------
array[@]=
"the      quick   brown"
array[@]=
"    fox jumped over    the"
array[@]=
"lazy    dogs back    "
----------
array[*]=
"the      quick   brown     fox jumped  over    the lazy    dogs back    "

一些非显而易见的关键点,以确保您的数组完全填充您的命令输出:

  1. 如果您的命令输出可以包含通配符,则应该在命令(oSET="$-"; set -f)之前禁用通配符并在之后重新启用它(set +f -$oSET)。
  2. 如果您的命令输出可以包含空格,则在命令(oIFS="$IFS"; IFS=$'\n')之前将IFS设置为换行符,并在命令(IFS="$oIFS")之后将其设置为旧值。 / LI>

答案 1 :(得分:2)

tmp=$(w | awk '{print $1}')

while read i
do
    echo "$i"
done <<< "$tmp"

答案 2 :(得分:1)

你可以使用for循环,即

for user in $(w | awk '{print $1}'); do echo $user; done

在脚本中看起来更好:

for user in $(w | awk '{print $1}')
do
    echo $user
done

答案 3 :(得分:0)

您可以使用xargs命令执行此操作:

w | awk '{print $1}' | xargs -I '{}' id '{}'

使用-I开关,xargs将分别获取其标准输入的每一行,然后通过使用输入行替换命令行模板中的指定字符串'{}'来构造和执行命令行

答案 4 :(得分:0)

我猜您应该使用who代替w。试试这个,

who | awk '{print $1}' | xargs -n 1 id