我有两个yaml文件正在使用。第一个yaml文件如下所示:
spring.yml
spring:
cloud:
gateway:
routes:
- id: someid
uri: someUri
predicates:
- Path=/somePath
filters:
- RewritePath=/someOtherPath我有另一个文件,它只包含路由,如下所示:
routes.yml
routes:
- id: someid
uri: someOtherUri
predicates:
- Path=/somePath
filters:
- RewritePath=/someNewPath我的目标是用第二个文件中路由的值更新第一个文件中的路由。注意,实际中的第一个文件将有许多路由,但为了演示目的,我只显示本例中的第一个。我有下面的脚本,当id匹配时,它循环起来更新路由:
#!/bin/sh
OVERRIDE_ROUTE_IDS=$(yq eval '.routes.[].id' routes.yml)
GENERATED_ROUTE_IDS=$(yq eval '.spring.cloud.gateway.routes.[].id' spring.yml)
SAVEIFS=$IFS # Save current IFS (Internal Field Separator)
IFS=$'\n' # Change IFS to newline char
OVERRIDE_ROUTE_IDS=($OVERRIDE_ROUTE_IDS) # split the `OVERRIDE_ROUTE_IDS` string into an array by the same name
GENERATED_ROUTE_IDS=($GENERATED_ROUTE_IDS) # split the `GENERATED_ROUTE_IDS` string into an array by the same name
IFS=$SAVEIFS # Restore original IFS
for (( i=0; i<${#OVERRIDE_ROUTE_IDS[@]}; i++ ))
do
if [[ "${GENERATED_ROUTE_IDS[*]}" =~ "${OVERRIDE_ROUTE_IDS[$i]}" ]]
then
echo "route ID ${OVERRIDE_ROUTE_IDS[$i]} exists in generated routes"
for (( j=0; j<${#GENERATED_ROUTE_IDS[@]}; j++ ))
do
if [[ "${GENERATED_ROUTE_IDS[$j]}" == "${OVERRIDE_ROUTE_IDS[$i]}" ]]
then
echo "index of route ${GENERATED_ROUTE_IDS[$j]} is $j"
echo "$i"
ROUTE_TO_USE=$(yq eval ".routes.[$i]" routes.yml)
$(yq ".spring.cloud.gateway.routes.[$j] = $ROUTE_TO_USE" spring.yml)
fi
done
else
echo "no match so add to top of routes"
fi
done我的假设是,这个命令应该用新的路径来更新spring.yml文件,而不是用相同的id标识的路径:
$(yq ".spring.cloud.gateway.routes.[$j] = $ROUTE_TO_USE" application.yml)但是我得到了以下错误
Error: Parsing expression: Lexer error: could not match text starting at 1:37 failing at 1:39 unmatched text: "id"我被困在这件事上,不知道自己在做什么。作为参考,我使用的是yq版本4.17.2。
发布于 2022-02-01 13:40:53
请注意,yq不会发出数据结构,它会发出一个字符串。例如,$ROUTE_TO_USE将是,
id: someid
uri: someOtherUri
predicates:
- Path=/somePath
filters:
- RewritePath=/someNewPath这是YAML的来源。将其粘贴到以下yq命令中将导致无效语法;yq的表达式语法不是文字YAML。这是错误试图告诉您的。
您要做的是在一个yq命令中处理两个输入:
yq ea "select(fi==0).spring.cloud.gateway.routes.[$j] = "`
`"select(fi==1).routes.[$i] | select(fi==0)" spring.yml routes.ymlea是eval-all的缩写,您需要它同时处理多个输入文件。fi是fileIndex的缩写,用于选择适当的文件。将结果传递给| select(fi==0)确保只写入第一个(修改的)文件。为了提高可读性,我将长字符串拆分为多行using backticks。
发布于 2022-02-04 02:51:22
最后,我从yq的创建者那里得到了一个解决方案。下面的解决方案是我所使用的:
yq ea '
(select(fi==0) | .spring.cloud.gateway.routes.[].id) as $currentIds |
(select(fi==1) | [.routes.[] | select( [$currentIds != .id] | all )] ) as $newRoutes |
( $newRoutes + .spring.cloud.gateway.routes + .routes) as $routesToMerge |
(
(($routesToMerge | .[] | {.id: .}) as $item ireduce ({}; . * $item )) as $uniqueMap
| ( $uniqueMap | to_entries | .[]) as $item ireduce([]; . + $item.value)
) as $mergedArray
| select(fi == 0) | .spring.cloud.gateway.routes = $mergedArray
' spring.yml routes.yml这在id上是匹配的。如果有匹配,则使用routes.yml中的值。如果没有匹配,则将其添加到路由的顶部。
https://stackoverflow.com/questions/70932362
复制相似问题