首页 > 解决方案 > Shell 脚本输出数组到新行

问题描述

我有这个代码

#!/bin/bash
PACKAGE_PATH="/var/www"

prompt="Please select:"
options=( $(ls -l $PACKAGE_PATH | grep ^d | awk '{print $9}') )

PS3="$prompt "
select PACKAGE_NAME in "${options[@]}" ; do
    if (( REPLY == 1 + ${#options[@]} )) ; then
        exit

    elif (( REPLY > 0 && REPLY <= ${#options[@]} )) ; then
        # echo  "You picked $PACKAGE_NAME which is file $REPLY"
        break

    else
        echo "Invalid option. Try another one."
    fi
done

我的目标是将列表保持在新行中,而不是彼此相邻。有没有可能?

标签: bash

解决方案


select使用该COLUMNS变量计算显示其选项时要使用的列数(它会根据COLUMNS选项字符串的长度动态计算以最小化使用的行数)。这通常设置为终端的宽度,但您可以在脚本中更改它:

#!/usr/bin/env bash

package_path="/var/www"
# Populate the options array with just base names of subdirectories of package_path that start with "com."
mapfile -t -d '' options < \
        <(find "$package_path" -mindepth 1 -maxdepth 1 -type d -name "com.*" -printf "%f\0")

# Prevent bash from updating COLUMNS after every non-built-in command.
shopt -u checkwinsize
# And set it to an artificially low value so select displays a single column
saved_columns=$COLUMNS
COLUMNS=1
PS3="Please select: "
select package_name in "${options[@]}" ; do
    if (( REPLY == 1 + ${#options[@]} )) ; then
        exit

    elif (( REPLY > 0 && REPLY <= ${#options[@]} )) ; then
        echo  "You picked $package_name which is file $REPLY"
        break

    else
        echo "Invalid option. Try another one."
    fi
done

# Restore COLUMNS and checkwinsize for the rest of the script (If any)
# If doing this a lot, consider a function
shopt -s checkwinsize
COLUMNS=$saved_columns


而且由于我一直在评论zsh文件名扩展,因此该 shell 的版本不使用find. 它使用glob 限定符将扩展的文件名限制为仅目录,并使用修饰符仅扩展为基本名称而不是完整路径:

#!/usr/bin/env zsh

# Normally on by default, but just in case...
setopt bare_glob_qual

package_path="/var/www"

# List just directories in package_path starting with "com."
# Note change of variable name; options is used by zsh
dirs=( "$package_path"/com.*(/:t) )

saved_columns=$COLUMNS
COLUMNS=1
PROMPT3="Please select: "
select package_name in "${dirs[@]}" ; do
    if (( REPLY == 1 + ${#dirs[@]} )) ; then
        exit

    elif (( REPLY > 0 && REPLY <= ${#dirs[@]} )) ; then
        echo  "You picked $package_name which is file $REPLY"
        break

    else
        echo "Invalid option. Try another one."
    fi
done
COLUMNS=$saved_columns

推荐阅读