如何将bash数组变量转换为用换行符分隔的字符串?


43

我想写一个bash数组变量到一个文件,每个元素在一个新行上。我可以使用for循环执行此操作,但是有另一种(更干净的)方法来连接元素 \n

Answers:


48

这是一种利用bash参数扩展的方法 IFS 特殊变量。

$ System=('s1' 's2' 's3' 's4 4 4')
$ ( IFS=$'\n'; echo "${System[*]}" )

我们使用子shell来避免覆盖值 IFS 在当前的环境中。在那个子shell中,我们然后修改值 IFS 这样第一个字符就是换行符(使用 $'...' 引用)。最后,我们使用参数扩展将数组的内容打印为单个单词;每个元素由第一个字符分隔 IFS

要捕获变量:

$ var=$( IFS=$'\n'; echo "${System[*]}" )

如果你的bash足够新(4.2或更高版本),你可以(并且应该)仍然使用 printf 随着 -v 选项:

$ printf -v var "%s\n" "${System[@]}"

在任何一种情况下,您可能都不希望最终换行 var。要删除它:

$ var=${var%?}    # Remove the final character of var

谢谢,有没有办法将其输出到变量?
ACyclic

更新以显示如何捕获变量。
chepner

2
不应该是最后一个例子 var=${var%?} 代替?这不是正则表达式,所以 . 将仅匹配句点字符。
musiphil

23

您可以使用 printf 在自己的行上打印每个数组项:

 $ System=('s1' 's2' 's3' 's4 4 4')
 $ printf "%s\n"  "${System[@]}"
s1
s2
s3
s4 4 4

6
awk -v sep='\n' 'BEGIN{ORS=OFS="";for(i=1;i<ARGC;i++){print ARGV[i],ARGC-i-1?sep:""}}' "${arr[@]}"

要么

perl -le 'print join "\n",@ARGV' "${arr[@]}"

要么

python -c 'import sys;print "\n".join(sys.argv[1:])' "${arr[@]}"

要么

sh -c 'IFS=$'\''\n'\'';echo "$*"' '' "${arr[@]}"

要么

lua <(echo 'print(table.concat(arg,"\n"))') "${arr[@]}"

要么

tclsh <(echo 'puts [join $argv "\n"]') "${arr[@]}"

要么

php -r 'echo implode("\n",array_slice($argv,1));' -- "${arr[@]}"

要么

ruby -e 'puts ARGV.join("\n")' "${arr[@]}"

这就是我到目前为止所能提醒的一切。


2

以上解决方案就是这样,但原始问题要求输出到文件:

$ a=(a b c d e)
$ ( IFS=$'\n'; echo "${a[*]}" ) > /tmp/file
$ cat /tmp/file
a
b
c
d
e
$

笔记: 1)'echo'提供最终换行符 2)如果再次使用bash读入此文件,则声明-p可能是所需的序列化。


2

运用 对于

for each in "${alpha[@]}"
do
  echo "$each"
done

运用 历史 ;请注意,如果您的值包含,这将失败 !

history -p "${alpha[@]}"

运用 基本名 ;请注意,如果您的值包含,这将失败 /

basename -a "${alpha[@]}"

运用 SHUF ;请注意,结果可能不会按顺序排出:

shuf -e "${alpha[@]}"

-1

printf 似乎是从数组创建分隔字符串的最有效方法:

# create a delimited string; note that printf doesn't put the trailing delimiter
# need to save and restore IFS
# it is prudent to put the whole logic on a single line so as to minimize the risk of future code changes breaking the sequence of saving/restoring of IFS
oldIFS=$IFS; IFS=$'\n'; printf -v var "${arr[*]}"; IFS=$oldIFS

# print string to file; note that the newline is required in the format string because printf wouldn't put a trailing delimiter (which is a good thing)
printf '%s\n' "$var" > file

更简单的方法是:

delim=$'\n'
printf -v var "%s$delim" "${arr[@]}" # create a delimited string
var="${var%$delim}"                  # remove the trailing delimiter

delim=:
arr=(one two three)
printf -v var "%s$delim" "${arr[@]}" # yields one:two:three:
var="${var%$delim}"                  # yields one:two_three

1
Downvoter,请评论这里有什么问题。
codeforester
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.