如何在BASH中的列中输出数组的内容

时间:2022-10-09 15:42:12

I wanted to display a long list of strings from an array.

我想从一个数组中显示一个长长的字符串列表。

Right now, my script run through a for loop echoing each value to the standard output:

现在,我的脚本运行了一个for循环,每个值都对应于标准输出:

for value in ${values[@]}
do
  echo $value
done

Yeah, that's pretty ugly! And the one column listing is pretty long too...

是的,这很丑!其中一列也很长……

I was wondering if i can find a command or builtin helping me to display all those values in columns, like the ls command does by default when listing a directory (ls -C).

我想知道是否可以找到一个命令或内建命令来帮助我在列中显示所有这些值,就像ls命令在列出目录时默认执行的那样(ls -C)。

[Update]

(更新)

Losing my brain with column not displaying properly formatted columns, here's more info:

如果列没有显示正确格式的列,我的大脑就会失去知觉,这里有更多的信息:

The values: $ values=( 01----7 02----7 03-----8 04----7 05-----8 06-----8 07-----8 08-----8 09---6 10----7 11----7 12----7 13----7 14-----8 15-----8 16----7 17----7 18---6 19-----8 20-----8 21-----8) (Notice the first two digits as an index and the last one indicating the string length for readability)

值:$值=(01 - - - - - 7 02——7 03 - - - - - 8 04——7 05——06年8——8 8 07——08——09年8——10 6——7 11 - - - - - 7 12 7——13——14 7——8 15 7——8 16——17——19 7 18 - 6——8 20 - - - - - 8 21 - - - - - 8)(注意前两个数字索引和最后一个显示可读性的字符串长度)

The command: echo " ${values[@]/%/$'\n'}" | column

命令:echo $ {值[@]/ % $ ' \ n ' }”|列

The result: bad columns http://tychostudios.ch/multipurpose/bad_columns.png

结果是:坏列http://tychostudios.ch/multi/bad_columns.png。

Something is going wrong...

一定是什么地方出了问题……

7 个解决方案

#1


17  

You could pipe your output to column.

您可以将输出传输到列。

column seems to struggle with some data in a single-column input being narrower than a tabstop (8 characters).

在单列输入中,列似乎很难处理比tabstop(8个字符)更窄的数据。

Using printf within a for-loop to pad values to 8 characters seems to do the trick:

在for循环中使用printf将值填充为8个字符似乎可以达到以下目的:

for value in "${values[@]}"; do 
    printf "%-8s\n" "${value}"
done | column

#2


4  

Here are a couple of techniques that can be used with Johnsyweb's answer so you can do your output without a loop:

这里有一些技巧可以用于Johnsyweb的回答,这样您就可以不需要循环地进行输出:

saveIFS=$IFS
IFS=$'\n'
echo "${values[*]}" | column
IFS=$saveIFS

or

echo " ${arr[@]/%/$'\n'}" | column

or

echo " ${arr[@]/%/$'\n'}" | sed 's/^ //' | column

#3


1  

It may look overkill, but i came up with my own solution. I wrote a little script that does exactly what i wanted: take a list of values and output them in a pretty formatted column view.

这看起来有些过头了,但我想出了自己的解决方案。我编写了一个小脚本,它所做的正是我想要的:获取一个值列表,并将它们输出到一个非常格式化的列视图中。

http://github.com/Arko/Columnize

http://github.com/Arko/Columnize

#4


1  

I know this is an old thread, but I get erratic results from column so I thought I'd give my solution. I wanted to group every 3 lines into 3 evenly spaced columns.

我知道这是一个旧的线程,但是我从列中得到了不稳定的结果,所以我想我应该给出我的解。我想把每3行都分成3列。

cat file.txt | xargs printf '%-24s\n' | sed '$p;N;s/\n//;$p;N;s/\n//'

Basically, it pipes each line into printf, which left-aligns it into a 24-character-wide block of whitespace, which is then piped into sed. sed will look ahead 2 lines into the future and remove the line break.

基本上,它将每一行都连接到printf中,它将它左对齐到一个24字符宽的空白块中,然后将其导入sed。sed将展望未来两行,并删除换行符。

The N command reads the next line into the current buffer, and s/\n// removes the line break. In short, what we want is 'N;N;s/\n//g', which will work in some cases. The problem is, if there aren't two extra lines to throw in the buffer, sed will quit suddenly. The $p commands pre-empt that by saying "If this is the last line, print the buffer contents immediately".

N命令将下一行读入当前缓冲区,并将s/\ N /删除换行符。简而言之,我们想要的是“N;N;s/\ N //g”,这在某些情况下是可行的。问题是,如果在缓冲区中没有额外的两行代码,那么sed将会突然停止。$p命令先发制人:“如果这是最后一行,立即打印缓冲区内容”。

#5


1  

I know it's an old thread but I ran into this same situation. I ended up combining a few ideas from here.

我知道这是一条老路,但我遇到了同样的情况。最后我结合了一些想法。

For the column utility based solution (without initial space issue):

基于列实用程序的解决方案(没有初始空间问题):

(IFS=''; echo "${values[*]/%/$'\n'}") | column

Using @Arko's script for basis, this can handle values with spaces. Notice the printf spec of %-*s for left justified colums and right would drop the '-'. I didn't include my terminal guessing but it is settable (terminalWidth).

使用@Arko的脚本作为基础,它可以处理带有空格的值。请注意左对齐列的%-*的printf规范,右边将删除'-'。我没有包括我的终端猜测,但它是可设置的(终端宽度)。

#  e.g.  column "$@"
#        spacing=4 column "$@"
#        left=6 spacing=3 column "$@"
#
function column() {
    local leftMargin=${left:-0}
    local padding=${spacing:-2}
    local maxWidth=$(( ${terminalWidth:-80} - $leftMargin ))
    local values=("$@")
    local max=$(( $(IFS=''; echo "${values[*]/%/$'\n'}" | wc -L) + $padding ))
    local cols=$(( $maxWidth / $max ))

    local pos=0 NL=''
    for value in "${values[@]}"; do
        [[ $pos == 0 ]] && {
            printf "$NL%*s" "$leftMargin"
            NL=$'\n'  # add newlines from now on...
        }
        printf "%-*s" "$max" "$value"
        (( pos = ($pos + 1) % $cols ))
    done
    echo

}

}

#6


0  

Tabspaces


Use a tab after each value.

在每个值之后使用一个标签。

( It automatically flows to next line too... )

(它也自动流到下一行……)

for value in ${values[@]}
do
  echo -en "$value\t"
done

Detailed info here

详细的信息在这里

GoodLUCK!!
- CVS

古德勒克! !-简历

#7


0  

For some reason column doesn't work for me. In my case I have an array like

因为某些原因,列对我不起作用。在我的例子中,我有一个像这样的数组

$ array = ( 1 2 3 dir1 dir2 dir3 )
$
$ echo ${array[@]} | column            
1 2 3 dir1 dir2 dir3

instead I used

相反,我使用

$ echo ${array[@]} | tr ' ' '\n' | sort
1
2
3
dir1
dir2
dir3

#1


17  

You could pipe your output to column.

您可以将输出传输到列。

column seems to struggle with some data in a single-column input being narrower than a tabstop (8 characters).

在单列输入中,列似乎很难处理比tabstop(8个字符)更窄的数据。

Using printf within a for-loop to pad values to 8 characters seems to do the trick:

在for循环中使用printf将值填充为8个字符似乎可以达到以下目的:

for value in "${values[@]}"; do 
    printf "%-8s\n" "${value}"
done | column

#2


4  

Here are a couple of techniques that can be used with Johnsyweb's answer so you can do your output without a loop:

这里有一些技巧可以用于Johnsyweb的回答,这样您就可以不需要循环地进行输出:

saveIFS=$IFS
IFS=$'\n'
echo "${values[*]}" | column
IFS=$saveIFS

or

echo " ${arr[@]/%/$'\n'}" | column

or

echo " ${arr[@]/%/$'\n'}" | sed 's/^ //' | column

#3


1  

It may look overkill, but i came up with my own solution. I wrote a little script that does exactly what i wanted: take a list of values and output them in a pretty formatted column view.

这看起来有些过头了,但我想出了自己的解决方案。我编写了一个小脚本,它所做的正是我想要的:获取一个值列表,并将它们输出到一个非常格式化的列视图中。

http://github.com/Arko/Columnize

http://github.com/Arko/Columnize

#4


1  

I know this is an old thread, but I get erratic results from column so I thought I'd give my solution. I wanted to group every 3 lines into 3 evenly spaced columns.

我知道这是一个旧的线程,但是我从列中得到了不稳定的结果,所以我想我应该给出我的解。我想把每3行都分成3列。

cat file.txt | xargs printf '%-24s\n' | sed '$p;N;s/\n//;$p;N;s/\n//'

Basically, it pipes each line into printf, which left-aligns it into a 24-character-wide block of whitespace, which is then piped into sed. sed will look ahead 2 lines into the future and remove the line break.

基本上,它将每一行都连接到printf中,它将它左对齐到一个24字符宽的空白块中,然后将其导入sed。sed将展望未来两行,并删除换行符。

The N command reads the next line into the current buffer, and s/\n// removes the line break. In short, what we want is 'N;N;s/\n//g', which will work in some cases. The problem is, if there aren't two extra lines to throw in the buffer, sed will quit suddenly. The $p commands pre-empt that by saying "If this is the last line, print the buffer contents immediately".

N命令将下一行读入当前缓冲区,并将s/\ N /删除换行符。简而言之,我们想要的是“N;N;s/\ N //g”,这在某些情况下是可行的。问题是,如果在缓冲区中没有额外的两行代码,那么sed将会突然停止。$p命令先发制人:“如果这是最后一行,立即打印缓冲区内容”。

#5


1  

I know it's an old thread but I ran into this same situation. I ended up combining a few ideas from here.

我知道这是一条老路,但我遇到了同样的情况。最后我结合了一些想法。

For the column utility based solution (without initial space issue):

基于列实用程序的解决方案(没有初始空间问题):

(IFS=''; echo "${values[*]/%/$'\n'}") | column

Using @Arko's script for basis, this can handle values with spaces. Notice the printf spec of %-*s for left justified colums and right would drop the '-'. I didn't include my terminal guessing but it is settable (terminalWidth).

使用@Arko的脚本作为基础,它可以处理带有空格的值。请注意左对齐列的%-*的printf规范,右边将删除'-'。我没有包括我的终端猜测,但它是可设置的(终端宽度)。

#  e.g.  column "$@"
#        spacing=4 column "$@"
#        left=6 spacing=3 column "$@"
#
function column() {
    local leftMargin=${left:-0}
    local padding=${spacing:-2}
    local maxWidth=$(( ${terminalWidth:-80} - $leftMargin ))
    local values=("$@")
    local max=$(( $(IFS=''; echo "${values[*]/%/$'\n'}" | wc -L) + $padding ))
    local cols=$(( $maxWidth / $max ))

    local pos=0 NL=''
    for value in "${values[@]}"; do
        [[ $pos == 0 ]] && {
            printf "$NL%*s" "$leftMargin"
            NL=$'\n'  # add newlines from now on...
        }
        printf "%-*s" "$max" "$value"
        (( pos = ($pos + 1) % $cols ))
    done
    echo

}

}

#6


0  

Tabspaces


Use a tab after each value.

在每个值之后使用一个标签。

( It automatically flows to next line too... )

(它也自动流到下一行……)

for value in ${values[@]}
do
  echo -en "$value\t"
done

Detailed info here

详细的信息在这里

GoodLUCK!!
- CVS

古德勒克! !-简历

#7


0  

For some reason column doesn't work for me. In my case I have an array like

因为某些原因,列对我不起作用。在我的例子中,我有一个像这样的数组

$ array = ( 1 2 3 dir1 dir2 dir3 )
$
$ echo ${array[@]} | column            
1 2 3 dir1 dir2 dir3

instead I used

相反,我使用

$ echo ${array[@]} | tr ' ' '\n' | sort
1
2
3
dir1
dir2
dir3