function cecho_multitext () {
# usage : cecho_multitext message_array color_array
# what it does : Multiple Colored-echo.
local -n array_msgs=$1
local -n array_colors=$2
# printf '1: %q\n' "${array_msgs[@]}"
# printf '2: %q\n' "${array_colors[@]}"
local i=0
local coloredstring=""
local normalcoloredstring=""
# check array counts
# echo "msg size : "${#array_msgs[@]}
# echo "col size : "${#array_colors[@]}
[[ "${#array_msgs[@]}" -ne "${#array_colors[@]}" ]] && exit 2
# build the colored string
for msg in "${array_msgs[@]}"
do
color=${array_colors[$i]}
coloredstring="$coloredstring $color $msg "
normalcoloredstring="$normalcoloredstring $msg"
# echo -e "coloredstring ($i): $coloredstring"
i=$((i+1))
done
# DEBUG
# echo -e "colored string : $coloredstring"
# echo -e "normal color string : $normal $normalcoloredstring"
# use either echo or printf as follows :
# echo -e "$coloredstring"
printf '%b\n' "${coloredstring}"
return
}
调用函数:
#!/bin/bash
green='\E[32m'
cyan='\E[36m'
white='\E[37m'
normal=$(tput sgr0)
declare -a text=("one" "two" "three" )
declare -a color=("$white" "$green" "$cyan")
cecho_multitext text color
encode_array(){
local array=($@)
echo -n "${array[@]}" | base64
}
decode_array(){
echo -n "$@" | base64 -d
}
some_func(){
local arr1=($(decode_array $1))
local arr2=($(decode_array $2))
local arr3=($(decode_array $3))
echo arr1 has ${#arr1[@]} items, the second item is ${arr1[2]}
echo arr2 has ${#arr2[@]} items, the third item is ${arr2[3]}
echo arr3 has ${#arr3[@]} items, the here the contents ${arr3[@]}
}
a1=(ab cd ef)
a2=(gh ij kl nm)
a3=(op ql)
some_func "$(encode_array "${a1[@]}")" "$(encode_array "${a2[@]}")" "$(encode_array "${a3[@]}")"
输出为
arr1 has 3 items, the second item is cd
arr2 has 4 items, the third item is kl
arr3 has 2 items, the here the contents op ql
无论如何,这将不适用于有制表符或空格的值。如果需要,我们需要一个更详细的解决方案。类似于:
encode_array()
{
for item in "$@";
do
echo -n "$item" | base64
done | paste -s -d , -
}
decode_array()
{
local IFS=$'\2'
local -a arr=($(echo "$1" | tr , "\n" |
while read encoded_array_item;
do
echo "$encoded_array_item" | base64 -d;
echo "$IFS"
done))
echo "${arr[*]}";
}
test_arrays_step1()
{
local IFS=$'\2'
local -a arr1=($(decode_array $1))
local -a arr2=($(decode_array $2))
local -a arr3=($(decode_array $3))
unset IFS
echo arr1 has ${#arr1[@]} items, the second item is ${arr1[1]}
echo arr2 has ${#arr2[@]} items, the third item is ${arr2[2]}
echo arr3 has ${#arr3[@]} items, the here the contents ${arr3[@]}
}
test_arrays()
{
local a1_2="$(echo -en "c\td")";
local a1=("a b" "$a1_2" "e f");
local a2=(gh ij kl nm);
local a3=(op ql );
a1_size=${#a1[@])};
resp=$(test_arrays_step1 "$(encode_array "${a1[@]}")" "$(encode_array "${a2[@]}")" "$(encode_array "${a3[@]}")");
echo -e "$resp" | grep arr1 | grep "arr1 has $a1_size, the second item is $a1_2" || echo but it should have only $a1_size items, with the second item as $a1_2
echo "$resp"
}
5条答案
按热度按时间gudnpqoy1#
shell将一个参数向量(也就是说,一个简单的C字符串数组)传递给正在运行的程序。这是操作系统级别的限制:在参数列表中的两个程序(任何两个程序,用任何语言编写的!)之间传递结构化数据,* 不存在任何方法 *,除非在这个C字符串数组成员的内容中对该结构进行编码。
方法:长度前缀
如果效率是一个目标(在易于解析和超出命令行和环境存储的
ARG_MAX
限制的空间使用量方面),一种可以考虑的方法是在每个数组前面加上一个描述其长度的参数。但是,通过提供长度参数,可以指示参数列表的哪些部分应该是给定数组的一部分:
...然后,在脚本内部,您可以使用length参数将内容拆分回数组:
如果以
./myScript 3 a b c 2 X Y 1 z
运行,则输出如下:方法:每个参数的数组名称前缀
顺便说一句,Python世界(尤其是
argparse
library的用户)的一个常见做法是允许一个参数被多次传递以修改给定的数组。在shell中,这看起来像这样:然后解析它的代码可能如下所示:
因此,如果原始值为
array1=( one two three ) array2=( aye bee ) array3=( "hello world" )
,则调用约定为:方法:以NULL分隔的流
另一种方法是为每个数组传递一个文件名,从中可以读取以NULL分隔的数组内容列表。这种方法的一个主要优点是,数组内容的大小不计入
ARG_MAX
(操作系统强制的命令行长度限制)。此外,在操作系统中,下面的代码并不创建真实的的磁盘文件,而是创建/dev/fd
样式的链接,链接到由subshell写入每个数组内容的FIFO。......并读取(使用bash 4.4或更高版本,提供
mapfile -d
):...或者,要支持较旧的bash版本,请执行以下操作:
r9f1avp52#
Charles Duffy的响应非常好用,但我想换一种方式,这样在脚本中初始化
var1
、var2
和var3
就更简单了:然后在
myScript.sh
中编辑:既然查尔斯已经简化了他的解,这很可能是一个比我的更好、更清晰的解。
fquxozlt3#
下面是一个代码示例,它展示了如何将2个数组传递给一个函数。除了提供了一个完整的代码示例外,没有比前面的答案更多的内容。
这在
bash 4.4.12
中编码,即在bash 4.3
之后,这将需要不同的编码方法。一个数组包含要着色的文本,另一个数组包含用于每个文本元素的颜色:调用函数:
工作完成:-)
u1ehiz5o4#
我更喜欢使用base64对数组进行编码和解码,例如:
输出为
无论如何,这将不适用于有制表符或空格的值。如果需要,我们需要一个更详细的解决方案。类似于:
t5zmwmid5#
根据此question的答案,您可以尝试以下操作。
将数组定义为shell上的变量:
有这样一个脚本:
并这样称呼它:
请注意,脚本需要是sourced(.或source),以便在当前shell环境而不是子shell中执行。