Bash Mapfile 变量添加 Space
Bash Mapfile Var Adds Space
我很困惑为什么会这样。
我想将交互式提示中的多行 var 粘贴到 mapfile 中,然后像使用文件对象一样使用所述 mapfile。
出于某种原因我可以忍受回声中断并使用 printf 但为什么在将 mapfile var 分配给另一个(全局)var 时添加前导 space?
#!/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-----
对脚本的一些修复:
#!/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"
why this happens.
Adds leading space!
当然可以 - echo
用 space 分隔参数。
$ 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 时,这些参数由 space 分隔。
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 中的第一个字符连接,默认情况下为 space。在该上下文中它等于 ${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 "%s\n" "${a[*]}"; ) # well known method for printing arrays
+ IFS='|'
+ printf '%s\n' '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 Rationale for Shell and Utilities C.2.5 Parameters and Variables,它与 $*
$@
一起使用,但它与数组相同。
我很困惑为什么会这样。
我想将交互式提示中的多行 var 粘贴到 mapfile 中,然后像使用文件对象一样使用所述 mapfile。
出于某种原因我可以忍受回声中断并使用 printf 但为什么在将 mapfile var 分配给另一个(全局)var 时添加前导 space?
#!/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-----
对脚本的一些修复:
#!/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"
why this happens.
Adds leading space!
当然可以 - echo
用 space 分隔参数。
$ 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 时,这些参数由 space 分隔。
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 中的第一个字符连接,默认情况下为 space。在该上下文中它等于 ${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 "%s\n" "${a[*]}"; ) # well known method for printing arrays
+ IFS='|'
+ printf '%s\n' '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 Rationale for Shell and Utilities C.2.5 Parameters and Variables,它与 $*
$@
一起使用,但它与数组相同。