我很困惑为什么会发生这种情况。
我想将交互式提示中的多行var粘贴到地图文件中,然后像处理文件对象一样处理所述地图文件。
由于某种原因,我可以使用printf来处理回声中断,但为什么在将映射文件var分配给另一个(全局(var时添加前导空格?
#!/bin/bash
global_privkey=""
myfunc(){
local input_pattern
# Paste SSH privkey.
builtin echo "paste your privkey:"
builtin mapfile input_pattern
# Adds leading space!
builtin echo "echo (adds space):"
builtin echo "${input_pattern[@]}"
# Works.
builtin echo "printf (good):"
builtin printf "%s" "${input_pattern[@]}"
builtin echo
# Adds leading space!
global_privkey="${input_pattern[@]}"
}
myfunc
# Leading space!
builtin echo "global printf (adds space from var assignment):"
builtin printf "%s" "$global_privkey"
builtin echo
exit 0
输出:
arch :: ~/scripts % ./input_privkey_minimal.sh
paste your privkey:
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCzzWDcxsfWJ0NI15wBtPLqQPfryYDSZz8jN+eSk7+pdAAAALD7CKEF+wih
BQAAAAtzc2gtZWQyNTUxOQAAACCzzWDcxsfWJ0NI15wBtPLqQPfryYDSZz8jN+eSk7+pdA
AAAED6QmKlvu9ASHyHHBm7oLq7l2AMglXKq+uJ9IlbZBDbc7PNYNzGx9YnQ0jXnAG08upA
9+vJgNJnPyM355KTv6l0AAAAKHJvYmVydEAxMDItMTgyLTE1NS0zNS5pcC5hZnJpaG9zdC
5qb2J1cmcBAgMEBQ==
-----END OPENSSH PRIVATE KEY-----
echo (adds space):
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCzzWDcxsfWJ0NI15wBtPLqQPfryYDSZz8jN+eSk7+pdAAAALD7CKEF+wih
BQAAAAtzc2gtZWQyNTUxOQAAACCzzWDcxsfWJ0NI15wBtPLqQPfryYDSZz8jN+eSk7+pdA
AAAED6QmKlvu9ASHyHHBm7oLq7l2AMglXKq+uJ9IlbZBDbc7PNYNzGx9YnQ0jXnAG08upA
9+vJgNJnPyM355KTv6l0AAAAKHJvYmVydEAxMDItMTgyLTE1NS0zNS5pcC5hZnJpaG9zdC
5qb2J1cmcBAgMEBQ==
-----END OPENSSH PRIVATE KEY-----
printf (good):
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCzzWDcxsfWJ0NI15wBtPLqQPfryYDSZz8jN+eSk7+pdAAAALD7CKEF+wih
BQAAAAtzc2gtZWQyNTUxOQAAACCzzWDcxsfWJ0NI15wBtPLqQPfryYDSZz8jN+eSk7+pdA
AAAED6QmKlvu9ASHyHHBm7oLq7l2AMglXKq+uJ9IlbZBDbc7PNYNzGx9YnQ0jXnAG08upA
9+vJgNJnPyM355KTv6l0AAAAKHJvYmVydEAxMDItMTgyLTE1NS0zNS5pcC5hZnJpaG9zdC
5qb2J1cmcBAgMEBQ==
-----END OPENSSH PRIVATE KEY-----
global printf (adds space from var assignment):
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCzzWDcxsfWJ0NI15wBtPLqQPfryYDSZz8jN+eSk7+pdAAAALD7CKEF+wih
BQAAAAtzc2gtZWQyNTUxOQAAACCzzWDcxsfWJ0NI15wBtPLqQPfryYDSZz8jN+eSk7+pdA
AAAED6QmKlvu9ASHyHHBm7oLq7l2AMglXKq+uJ9IlbZBDbc7PNYNzGx9YnQ0jXnAG08upA
9+vJgNJnPyM355KTv6l0AAAAKHJvYmVydEAxMDItMTgyLTE1NS0zNS5pcC5hZnJpaG9zdC
5qb2J1cmcBAgMEBQ==
-----END OPENSSH PRIVATE KEY-----
为什么会发生这种情况。
添加前导空格!
当然可以-echo
用空格分隔参数。
$ echo '1' "2" 3
1 2 3 # wow single spaces
$ a=(1 2 '3 var with spaces')
$ echo "${a[@]}"
1 2 3 var with spaces # arguments contents are preserved
当您将多个参数传递给echo时,这些参数由空格分隔。
mapfile
不会从数组元素中删除尾随分隔符。因此,每个数组元素都以一条换行符结束。另外,echo
输出第二个换行符,因此打印出两个换行符从而产生一个空行。
$ a=(1$'n' 2$'n' 3$'n') # mapfile leaves newline in variables
$ set -x
$ echo "${a[@]}"
+ echo '1
' '2
' '3
' # executes echo with 3 arguments, each with a newline
1
2 # echo outputs values separated by spaces
3
# echo outputs extra newline
# the echo "${a[@]}" is equal to:
$ echo 1$'n' 2$'n' 3$'n'
1
2
3
$
当在分配中使用${array[@]}
扩展数组时,数组元素使用IFS中的第一个字符(默认为空格(进行连接。在该上下文中,它等于${array[*]}
(因为"单词"在赋值时被连接在一起(。
$ set -x
$ a=(1 2 3)
+ a=(1 2 3)
$ echo "${a[@]}"
+ echo 1 2 3 # passes 3 arguments
1 2 3
$ echo "${a[*]}"
+ echo '1 2 3' # passes 1 argument separated by first character in IFS
1 2 3
$ ( IFS='|'; printf "%sn" "${a[*]}"; ) # well known method for printing arrays
+ IFS='|'
+ printf '%sn' '1|2|3'
1|2|3
$ b="${a[@]}"
+ b='1 2 3' # wow, spaces
$ b="${a[*]}"
+ b='1 2 3' # * will be equal to @ in assignment
使用[*]
和[@]
的数组扩展的处理方式类似于使用位置自变量的$*
和$@
。对于更广泛的示例,我推荐Posix Reason For Shell and Utilities C.2.5参数和变量,它与$*
$@
相同,但与阵列相同。
对脚本的一些修复:
#!/usr/bin/env bash
global_privkey=""
myfunc(){
local input_pattern
# Paste SSH privkey.
echo "paste your privkey:"
mapfile -t input_pattern
# Adds leading space!
echo "echo (adds space):"
echo "${input_pattern[@]}"
# Works.
echo "printf (good):"
printf %s\n "${input_pattern[@]}"
echo
# Delete BEGIN END entries
unset 'input_pattern[0]' 'input_pattern[-1]'
# Join lines into a single string
printf -v global_privkey %s "${input_pattern[@]}"
}
myfunc
# Leading space!
echo "global printf (adds space from var assignment):"
printf %s\n "$global_privkey"