bash:获取数组多个元素的更简单方法是什么?

3
有没有*nix命令,可以按照每行最大元素数格式化输入(由换行符分隔)?例如: $ yes x | head -10 | command 4 x x x x x x x x x x
我写了一个快速的bash脚本(如下所示),来执行此任务,但它似乎很长并且可能效率低下。有更好的方法来做到这一点吗?
#!/bin/sh

if [ -z "$1" -o -z "$2" ]; then
        echo Usage `basename $0` {rows} {columns}
        exit 1
fi

ROWS=$1
COLS=$2

input=$(yes x | head -${ROWS})
lines=()
i=0
j=0
eol=0

for x in ${input[*]}
do
        lines[$i]="${lines[$i]} $x"
        j=`expr $j + 1`
        eol=0
        if [ $j -ge ${COLS} ]; then
                echo lines[$i] = ${lines[$i]}
                i=`expr $i + 1`
                j=0
                eol=1
        fi
done

if [ ${eol} -eq 0 ]; then
        echo lines[$i] = ${lines[$i]}
fi

对于变量 x 在 "${input[@]}" 中迭代, 递增 j 的值, 如果 j 大于等于 COLS, 访问 lines 数组的第 i 个元素, 输出 "...", 等等。 - Dennis Williamson
5个回答

8

数组可以被切片。

$ foo=(q w e r t y u)
$ echo "${foo[@]:0:4}"
q w e r

4
printf '%-10s%-10s%-10s%s\n' $(command | command)

printf会按照格式字符串中指定的参数数量一次性消耗它们,并在全部消耗完之前继续执行。

示例:

$ printf '%-10s%-10s%-10s%s\n' $(yes x | head -n 10)
x         x         x         x
x         x         x         x
x         x
$ printf '%-10s%-10s%-10s%s\n' $(<speech)
now       is        the       time
for       all       good      men
to        come      to        the
aid       of        their     country

@user46874:以下是如何动态构建格式字符串,给定字段数包含在$n中:printf -v format '%*s' "$n" ''; format="${format// /%-10s}\n"; printf "$format" $(...)。最后一个字段将有尾随空格,但这可能不是问题。如果是的话,在第一步中使用$((n - 1)),第二步将是format="${format// /%-10s}%s\n" - Dennis Williamson

1
yes x | head -10 | awk 'BEGIN { RS = "%%%%%%%" } { split($0,a,"\n"); for (i=1; i<length(a); i+=4) print a[i], a[i+1], a[i+2], a[i+3] }'

更易读:

yes x | \
head -10 | \
awk 'BEGIN { RS = "%%%%%%%" }
     { split($0,a,"\n"); 
       for (i=1; i<length(a); i+=4) print a[i], a[i+1], a[i+2], a[i+3] }'

0

你可以使用xargs(1)来实现这个功能,使用-n或者--max-args=选项来限制每个命令行的参数数量:

$ yes x | head -10 | xargs -n4
x x x x
x x x x
x x
$

显然,您必须能够信任输入;例如,如果引号不匹配,xargs就会出现问题:

$ yes 'x"' | head -10 | xargs -n4
xargs: unmatched double quote; by default quotes are special to xargs unless you use the -0 option
$

0

为什么不试试这样的东西

sed 's|\(.{10}\)|\1\n|'

我正在使用Windows机器,还没有尝试过这个。我的想法是匹配N次所有内容,并将它们替换为匹配的模式加上换行符。

附言:请纠正sed表达式中的任何语法错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接