如何将 YAML 的子集转换为关联数组的索引数组?
How to convert a subset of YAML into an indexed array of associative arrays?
我在 linux.
上使用 Bash 4.3
我有这个简单的 YAML 式数据文件:
products:
product1:
name: "Product one"
price: 100
product2:
name: "Product two"
price: 200
myList:
- one
- two
我需要一个 shell 函数,以上述 YAML 文件作为输入,可以 生成然后执行 下面的 Bash 代码:
unset products product1 product2
# declare the associative arrays
declare -A product1
declare -A product2
# define the data
product1=(
[name]="Product 1"
[price]=100
)
product2=(
[name]="Product 2"
[price]=200
)
myList=(one two)
# declare the arrays which will contain the names of our associative arrays
products=(product1 product2)
一旦我有了这个美妙的功能,我将使用 YAML 文件自动生成数据,以便在我的自定义 CMS 模板系统中使用,如下所示:
{{#foreach product in products}}
<h3>{{product.name | uppercase}}</h3>
* {{product.price | money_with_currency £ GBP | without_trailing_zeros}}
{{/foreach}}
我已经尝试过各种 YAML 解析器,但还没有找到可以生成我需要的关联数组的解析器,而且有些根本不起作用(至少对我而言):
- https://github.com/ArtBIT/bash-yaml
- https://github.com/luodongseu/shyaml
- https://github.com/binaryphile/y2s
- https://github.com/Hashfyre/yamlparser
- https://github.com/ash-shell/yaml-parse
- https://github.com/jasperes/bash-yaml
- https://github.com/mrbaseman/parse_yaml
- https://github.com/azohra/yaml.sh
- https://github.com/Minlison/yaml-parser
- https://gist.github.com/pkuczynski/8665367
其中大部分,据我了解它们的用法会生成类似 product_product1_name="foo"
:(
您在问题中链接的 yaml.sh
是一个非常好的解析器。将其输出转换为您需要的格式比执行任何其他操作要容易得多。
cleanupValue() {
local result
case in
'"'*'"') result=${1#'"'}; result=${result%'"'} ;;
"["*"]") result=${1#'['}; result=${result%']'} ;;
*) result=
esac
printf '%s\n' "$result"
}
record_data() {
local key value="$(cleanupValue "")"; shift
while (( $# >= 2 )); do
key=$(cleanupValue "")
if (( $# > 2 )); then
declare -g -a "" || continue
declare -g -A "___seen" || continue
local -n __array=""
local -n __seen_array="___seen"
if ! [[ ${__seen_array[$key]} ]]; then
__seen_array[$key]=1
__array+=( "$key" )
fi
unset -n __seen_array
else
declare -g -A "" || continue # "continue" to skip invalid variable names
local -n __array="" || continue
__array[$key]=$value
fi
unset -n __array
shift
done
}
while IFS='=' read -r key value; do
IFS=. read -r -a key_pieces <<<"$key"
record_data "$value" "${key_pieces[@]}"
done < <(ysh -f your.yml)
# demonstrate results
declare -p products product1 product2 myList
...作为输出发出:
declare -a products=([0]="product1" [1]="product2")
declare -A product1=([price]="100" [name]="Product one" )
declare -A product2=([price]="200" [name]="Product two" )
declare -A myList=([1]="two" [0]="one" )
我在 linux.
上使用 Bash 4.3我有这个简单的 YAML 式数据文件:
products:
product1:
name: "Product one"
price: 100
product2:
name: "Product two"
price: 200
myList:
- one
- two
我需要一个 shell 函数,以上述 YAML 文件作为输入,可以 生成然后执行 下面的 Bash 代码:
unset products product1 product2
# declare the associative arrays
declare -A product1
declare -A product2
# define the data
product1=(
[name]="Product 1"
[price]=100
)
product2=(
[name]="Product 2"
[price]=200
)
myList=(one two)
# declare the arrays which will contain the names of our associative arrays
products=(product1 product2)
一旦我有了这个美妙的功能,我将使用 YAML 文件自动生成数据,以便在我的自定义 CMS 模板系统中使用,如下所示:
{{#foreach product in products}}
<h3>{{product.name | uppercase}}</h3>
* {{product.price | money_with_currency £ GBP | without_trailing_zeros}}
{{/foreach}}
我已经尝试过各种 YAML 解析器,但还没有找到可以生成我需要的关联数组的解析器,而且有些根本不起作用(至少对我而言):
- https://github.com/ArtBIT/bash-yaml
- https://github.com/luodongseu/shyaml
- https://github.com/binaryphile/y2s
- https://github.com/Hashfyre/yamlparser
- https://github.com/ash-shell/yaml-parse
- https://github.com/jasperes/bash-yaml
- https://github.com/mrbaseman/parse_yaml
- https://github.com/azohra/yaml.sh
- https://github.com/Minlison/yaml-parser
- https://gist.github.com/pkuczynski/8665367
其中大部分,据我了解它们的用法会生成类似 product_product1_name="foo"
:(
yaml.sh
是一个非常好的解析器。将其输出转换为您需要的格式比执行任何其他操作要容易得多。
cleanupValue() {
local result
case in
'"'*'"') result=${1#'"'}; result=${result%'"'} ;;
"["*"]") result=${1#'['}; result=${result%']'} ;;
*) result=
esac
printf '%s\n' "$result"
}
record_data() {
local key value="$(cleanupValue "")"; shift
while (( $# >= 2 )); do
key=$(cleanupValue "")
if (( $# > 2 )); then
declare -g -a "" || continue
declare -g -A "___seen" || continue
local -n __array=""
local -n __seen_array="___seen"
if ! [[ ${__seen_array[$key]} ]]; then
__seen_array[$key]=1
__array+=( "$key" )
fi
unset -n __seen_array
else
declare -g -A "" || continue # "continue" to skip invalid variable names
local -n __array="" || continue
__array[$key]=$value
fi
unset -n __array
shift
done
}
while IFS='=' read -r key value; do
IFS=. read -r -a key_pieces <<<"$key"
record_data "$value" "${key_pieces[@]}"
done < <(ysh -f your.yml)
# demonstrate results
declare -p products product1 product2 myList
...作为输出发出:
declare -a products=([0]="product1" [1]="product2")
declare -A product1=([price]="100" [name]="Product one" )
declare -A product2=([price]="200" [name]="Product two" )
declare -A myList=([1]="two" [0]="one" )