koo*_*ola 32 arrays string bash delimited-text
我想知道以下内容;
非工作的例子
> ids=(1 2 3 4);echo ${ids[*]// /|}
1 2 3 4
> ids=(1 2 3 4);echo ${${ids[*]}// /|}
-bash: ${${ids[*]}// /|}: bad substitution
> ids=(1 2 3 4);echo ${"${ids[*]}"// /|}
-bash: ${"${ids[*]}"// /|}: bad substitution
Run Code Online (Sandbox Code Playgroud)
工作实例
> ids=(1 2 3 4);id="${ids[@]}";echo ${id// /|}
1|2|3|4
> ids=(1 2 3 4); lst=$( IFS='|'; echo "${ids[*]}" ); echo $lst
1|2|3|4
Run Code Online (Sandbox Code Playgroud)
在上下文中,用于sed命令的分隔字符串用于进一步解析.
F. *_*uri 31
# REVISION: 2017-03-14
# Use of read and other bash specific features (bashisms)
Run Code Online (Sandbox Code Playgroud)
因为括号用于分隔数组,而不是字符串:
ids="1 2 3 4";echo ${ids// /|}
1|2|3|4
Run Code Online (Sandbox Code Playgroud)
一些示例:$ids用两个字符串填充: a b和c d
ids=("a b" "c d")
echo ${ids[*]// /|}
a|b c|d
IFS='|';echo "${ids[*]}";IFS=$' \t\n'
a b|c d
Run Code Online (Sandbox Code Playgroud)
......最后:
IFS='|';echo "${ids[*]// /|}";IFS=$' \t\n'
a|b|c|d
Run Code Online (Sandbox Code Playgroud)
组装数组时,由第一个char分隔$IFS,但|在数组的每个元素中用空格替换.
当你这样做时:
id="${ids[@]}"
Run Code Online (Sandbox Code Playgroud)
您将字符串构建从数组 合并ids空格转换为字符串类型的新变量.
注意:当"${ids[@]}"给出一个以空格分隔的字符串时,"${ids[*]}"(用星号*而不是at符号@)将呈现由第一个字符$IFS分隔的字符串.
man bash说什么:
man -Len -Pcol\ -b bash | sed -ne '/^ *IFS /{N;N;p;q}'
IFS The Internal Field Separator that is used for word splitting
after expansion and to split lines into words with the read
builtin command. The default value is ``<space><tab><newline>''.
Run Code Online (Sandbox Code Playgroud)
玩$IFS:
set | grep ^IFS=
IFS=$' \t\n'
Run Code Online (Sandbox Code Playgroud)
declare -p IFS
declare -- IFS="
"
printf "%q\n" "$IFS"
$' \t\n'
Run Code Online (Sandbox Code Playgroud)
字面意思a space,a tabulation和(意思或) a line-feed.所以,虽然第一个角色是一个空间.使用*会做同样的事情@.
但是:
{
Run Code Online (Sandbox Code Playgroud)
# OIFS="$IFS"
# IFS=$': \t\n'
# unset array
# declare -a array=($(echo root:x:0:0:root:/root:/bin/bash))
Run Code Online (Sandbox Code Playgroud)
IFS=: read -a array < <(echo root:x:0:0:root:/root:/bin/bash)
echo 1 "${array[@]}"
echo 2 "${array[*]}"
OIFS="$IFS" IFS=:
echo 3 "${array[@]}"
echo 4 "${array[*]}"
IFS="$OIFS"
}
1 root x 0 0 root /root /bin/bash
2 root x 0 0 root /root /bin/bash
3 root x 0 0 root /root /bin/bash
4 root:x:0:0:root:/root:/bin/bash
Run Code Online (Sandbox Code Playgroud)
注:该生产线IFS=: read -a array < <(...)将使用:作为分隔符,没有设置$IFS永久.这是因为输出行将#2空格显示为分隔符.
gni*_*urf 13
你的第一个问题已在F. Hauri的答案中得到解决.这是加入数组元素的规范方法:
ids=( 1 2 3 4 )
IFS=\| eval 'lst="${ids[*]}"'
Run Code Online (Sandbox Code Playgroud)
有些人会大声喊叫eval是邪恶的,但由于单引号,这里非常安全.这只有一个优点:没有子shell,IFS没有全局修改,它不会修剪尾随换行符,而且非常简单.
您也可以使用它printf,而无需任何外部命令或需要操纵IFS:
ids=(1 2 3 4) # create array
printf -v ids_d '|%s' "${ids[@]}" # yields "|1|2|3|4"
ids_d=${ids_d:1} # remove the leading '|'
Run Code Online (Sandbox Code Playgroud)
将参数数组连接到分隔字符串的实用程序函数:
#!/usr/bin/env bash
# Join arguments with delimiter
# @Params
# $1: The delimiter string
# ${@:2}: The arguments to join
# @Output
# >&1: The arguments separated by the delimiter string
array::join() {
(($#)) || return 1 # At least delimiter required
local -- delim="$1" str IFS=
shift
str="${*/#/$delim}" # Expands arguments with prefixed delimiter (Empty IFS)
printf '%s\n' "${str:${#delim}}" # Echo without first delimiter
}
declare -a my_array=( 'Paris' 'Berlin' 'London' 'Brussel' 'Madrid' 'Oslo' )
array::join ', ' "${my_array[@]}"
array::join '*' {1..9} | bc # 1*2*3*4*5*6*7*8*9=362880 Factorial 9
declare -a null_array=()
array::join '== Ultimate separator of nothing ==' "${null_array[@]}"
Run Code Online (Sandbox Code Playgroud)
输出:
Paris, Berlin, London, Brussel, Madrid, Oslo
362880
Run Code Online (Sandbox Code Playgroud)
现在有了 Bash 4.2+ 的 nameref 变量,不再需要使用子 shell 输出捕获。
Paris, Berlin, London, Brussel, Madrid, Oslo
362880
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
38991 次 |
| 最近记录: |