Arr*_*han 20 arrays bash shell
我有一个数组,我正在像这样打印它:
echo "${data[*]}"
Run Code Online (Sandbox Code Playgroud)
输出:
/QE-CI-RUN-71/workspace/QE-AU/57/testng-results_1.xml
/QE-CI-RUN-71/workspace/QE-AU/57/testng-results_2.xml
Run Code Online (Sandbox Code Playgroud)
我想将上述输出存储为逗号分隔值。我怎样才能在 Bash 中实现这一目标?
数据数组是动态的,它可以有任意数量的值。
Ada*_*atz 26
有几种方法可以做到这一点:
1.直接加入printf
(通过Charles Duffy 的评论)
printf -v joined '%s,' "${data[@]}"
echo "${joined%,}"
Run Code Online (Sandbox Code Playgroud)
该printf
内置隐含加入阵列。您可以像下面的 3a 一样使用单行阅读交互式打印printf '%s,' "${data[@]}"
,但会留下一个尾随逗号。(此方法甚至适用于 POSIX shell,但您必须将其$@
用作数组,因为 POSIX 无法处理其他数组类型)。
2.更改$IFS
字段分隔符(通过chepner的回答)
join_arr() {
local IFS="$1"
shift
echo "$*"
}
join_arr , "${data[@]}"
Run Code Online (Sandbox Code Playgroud)
这仅在此函数的范围内重新定义了字段分隔符,因此当$data
数组自动扩展时,它使用所需的分隔符而不是全局$IFS
或(如果为空或未定义)空间的第一个值。
这可以在没有函数的情况下完成,但是保留有些麻烦$IFS
:Charles Duffy 指出,IFS="$OLD_IFS"
在临时重新分配后恢复可以评估为IFS=""
,但是如果$IFS
以前未定义,则unset IFS
与可以将它们分开并且可以将它们分开,这种函数方法是由于使用了local
to limit$IFS
的范围,所以更干净。
3a. 循环遍历其内容(并逐步打印)
delim=""
for item in "${data[@]}"; do
printf "%s" "$delim$item"
delim=","
done
echo # add a newline
Run Code Online (Sandbox Code Playgroud)
如果该循环中的其他代码涉及外部调用(甚至sleep 0.1
),您实际上将逐块观看此构建,这在交互式设置中很有帮助。
3b. 循环遍历其内容(并构建一个变量)
delim=""
joined=""
for item in "${data[@]}"; do
joined="$joined$delim$item"
delim=","
done
echo "$joined"
Run Code Online (Sandbox Code Playgroud)
4.将数组保存为字符串并对其运行替换(注意,数组必须缺少空格*)
data_string="${data[*]}"
echo "${data_string//${IFS:0:1}/,}"
Run Code Online (Sandbox Code Playgroud)
* 这仅在$IFS
(默认情况下为空格)的第一个字符不存在于任何数组项中时才有效。
这将使用bash的模式替换:${parameter//pattern/string}
将更换的每个实例pattern
中$parameter
使用string
。在这种情况下,string
is ${IFS:0:1}
,$IFS
从一个字符开始到一个字符结束的子串。
Z Shell ( zsh
) 可以在一个嵌套参数扩展中做到这一点:
echo "${${data[@]}//${IFS:0:1}/,}"
Run Code Online (Sandbox Code Playgroud)
(尽管 Z Shell 也可以使用其专用join
标志更优雅地做到这一点,echo "${(j:,:)data}"
正如@DavidBaynard在此答案下方的评论中所指出的那样。)
为了更容易定位 的变化IFS
,请使用函数:
join () {
local IFS="$1"
shift
echo "$*"
}
join , "${data[@]}"
Run Code Online (Sandbox Code Playgroud)
如果您想用逗号分隔,请将其作为 中的第一个字符IFS
:
data=( first second third )
IFS=,
echo "${data[*]}"
Run Code Online (Sandbox Code Playgroud)
...发出:
first,second,third
Run Code Online (Sandbox Code Playgroud)
为了避免使 IFS 处于修改状态,您可以将此代码嵌入到函数中并将 IFS 声明为本地。如果您有 bash 4.3 或更高版本,则可以使用namevar支持来参数化保存到的变量输出,而无需子 shell 的开销:
comma_sep() {
local -n comma_sep__dest=$1; shift || return
local IFS=,
comma_sep__dest=$*
}
comma_sep result "${data[@]}"
echo "$result" # prints first,second,third
Run Code Online (Sandbox Code Playgroud)
小智 6
对于 ksh,试试这个!
foo=`echo $(echo ${data[@]}) | tr ' ' ','`
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您可以通过将空格(默认)转换为逗号来控制分隔符!(或任何其他你能想到的):)