【问题标题】:string concatenation from a bash array来自 bash 数组的字符串连接
【发布时间】:2018-05-08 21:35:00
【问题描述】:

我在尝试创建一个字符串时遇到了很多麻烦,该字符串是一个数组连接的结果,每次通过循环时都会加一点

# HERE IS THE VALUE OF CHANGELOG.JSON
# [
#   13,
#   14,
#   22
# ]

readarray -t lines <<<"$(cat $1/changelog.json | jq '.[]')"

echo "check if my array is filled"
echo ${lines[0]}
echo ${lines[1]}
echo ${lines[2]}
echo "my array is correctly filled.."

for i in ${!lines[@]}
do
    var2="$var2 | jq '.[$((($i+1)))]=${lines[$i]}'"
    echo "my var2 during loop: $var2"
done

echo "my var2 after loop $var2"

由于某些原因,这个脚本给了我这个作为输出

$ /bin/bash add-changelog.sh Blupods-front-v3/
check if my array is filled
13
14
22
my array is correctly filled..
'y var2 during loop:  | jq '.[1]=13
' | jq '.[2]=14loop:  | jq '.[1]=13
' | jq '.[3]=22'oop:  | jq '.[1]=13
' | jq '.[3]=22'op  | jq '.[1]=13

你们知道我怎样才能让它工作吗?我已经经历了很多关于stackoverflow的解决方案,但没有一个有效(使用+=进行连接)我听说过其他问题,这是因为for/while循环创建了一个子shell,但即使在循环变量不会被记住。我也没有任何管道,除了读取数组。

编辑:在这里我添加我的预期结果,也许它会帮助你们帮助我 我不是想马上执行这个命令,我只是想在 for 循环中连接一个字符串,预期的结果应该是这个

echo $var2
| jq '.[1]=13' | jq '.[2]=14 | jq '.[3]=22'

【问题讨论】:

  • var2="$var2 | jq '.[$((($i+1)))]=${lines[$i]}'" 应该做什么? var2 的初始值是多少?如果这是您所期望的,那么该分配将不会执行管道。它只会将整个字符串分配给 var2,而不是管道执行的结果。您需要$(...) 来执行管道。
  • 我不想立即执行它,我想连接该字符串并只在最后的循环之外执行它(这样做的最终目标是更新 json 文件)有var2 没有初始值
  • 请查看编辑以了解我想要实现的目标
  • 你想对$var2做什么?可能有一个解决方案不需要动态生成对jq 的多次调用的管道。
  • jq --slurpfile cl changelog.json '.[:3] = $cl[]' original.json 这样的东西可能会做你想做的事。

标签: arrays string bash loops concatenation


【解决方案1】:

如果 for 循环中有相应的行,这可能会有所帮助。

var2="$(echo "$var2" | jq '.[$((($i+1)))]=${lines[$i]}')"

【讨论】:

  • 我不想立即执行这个命令,我只是想在 for 循环中连接一个字符串,预期的结果应该是这样,请查看我的编辑以了解我想要实现的目标跨度>
  • @Rakiah:对不起,我现在明白你的目标了,谢谢你的编辑。我做了一些测试,发现-treadarray 没有我想要的效果。在您的情况下,这可能会在您的输出中出现这些奇怪的换行符。然而,变量替换让我更进一步。您能否尝试在for 循环的主体中使用${lines[$i]//$'\n'/} 而不仅仅是${lines[$i]}
  • 感谢您的宝贵时间,使用此行var2="$var2 | jq '.[$((($i+1)))]=${lines[$i]//$'\n'/}'" 我得到此输出'y var2 during loop: | jq '.[1]=17 ' | jq '.[2]=13 '.[1]=17 ' | jq '.[3]=14'.[1]=17
  • 但我确实相信 readarray -t 是问题所在,因为像这样创建的普通数组array=(13 17 22) 这给出的输出看起来更像我想要的
  • @Rakiah:看起来更好!你可以在循环之前做var2="" 吗?
【解决方案2】:

数组中的值似乎有\r 字符。您可以使用tr -d '\r' 删除它们。 其实我建议这样写:

lines=($(jq '.[]' < "$1"/changelog.json | tr -d '\r'))

虽然你的 for 循环是正确的,但它也可以改进:

var2=
for i in ${!lines[@]}; do
    var2="$var2 | jq '.[$((i+1))]=${lines[i]}'"
done

【讨论】:

  • 这没有做任何事情,因为“行”内没有任何内容
  • 我设法通过这样做而不是 lines=($(cat "$1"/changelog.json | jq '.[]' | tr -d '\r')) 使其工作跨度>
  • @Rakiah lines=($(jq '.[]' &lt; "$1"/changelog.json | tr -d '\r')) 怎么样?这应该是等效的,但没有无用的cat ;-)
  • 是的,没有 cat 的第二个解决方案就像 cat 一样工作,但是还有一个问题,如果我的 changelog.json 文件有一个包含空格的字符串数组,lines 数组包含更多键比每个值一个,由于某种原因,行数组每次遇到空格时也会拆分,您是否也有解决方案?还是谢谢你
  • 如果有人遇到同样的问题stackoverflow.com/questions/24628076/…,那么快速搜索可以为我找到答案@这行得通,现在一切都很好,谢谢 janos
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-29
  • 2014-04-03
  • 2011-02-18
  • 1970-01-01
  • 2022-01-20
相关资源
最近更新 更多