on bash 4.4.12使用jq 1.5和这个单行IFS=_ read -r -a a < <(jq -ncj '["a","b","c"][]+"_"') ; printf '%s\n' "${a[@]}"
我得到一个正确分隔的输出
一
B'/ P>
C
分别对于元素a,b和c,但是如果我尝试使用null定界符同样的事情:IFS= read -r -a a < <(jq -ncj '["a","b","c"][]+"\u0000"') ; printf '%s\n' "${a[@]}"
那么我只得到一个包含
ABC
为什么这不能像预期的那样工作?
此外,如果您尝试IFS= read -r -d '' -a a < <(jq -ncj '["a","b","c"][]+"\u0000"') ; printf '%s\n' "${a[@]}
,您会惊讶地发现只有第一个“ a ”元素的数组:
一
我的目标是找到一种方法,而不用任何类型的循环迭代元素。
编辑:**readarray -d**
不是解决方案,因为我需要在版本4.4之前的bash中运行该代码
答案 0 :(得分:4)
使用readarray
,-d
与read
bash
中的$ readarray -d $'\0' -t a < <(jq -ncj '["a","b","c"][]+"\u0000"')
$ declare -p a
declare -a a=([0]="a" [1]="b" [2]="c")
类似-d ''
获得''
:
readarray -d
while
也适用;由于shell字符串是空终止的,因此read
在技术上是包含空字符的字符串。
如果没有bash
支持,您可以使用a=()
while read -d '' -r item; do
a+=("$item")
done < <( jq -ncj '["a","b","c"][]+"\u0000"' )
循环const navButtonsMsg = new BotBuilder.Message(session)
.text("Hello")
.suggestedActions(
BotBuilder.SuggestedActions.create(
session,
[
BotBuilder.CardAction.imBack(session, "red", "red"),
BotBuilder.CardAction.imBack(session, "blue", "blue"),
BotBuilder.CardAction.imBack(session, "green", "green")
]
)
);
session.send(navButtonsMsg);
,该循环适用于任何版本的const navButtonsMsg = new BotBuilder.Message(session)
.suggestedActions(
BotBuilder.SuggestedActions.create(
session,
[
BotBuilder.CardAction.imBack(session, "red", "red"),
BotBuilder.CardAction.imBack(session, "blue", "blue"),
BotBuilder.CardAction.imBack(session, "green", "green")
]
)
);
session.send(navButtonsMsg);
:
data.table
这是你能做的最好的事情,除非你对数组元素有所了解,可以让你选择一个不属于任何元素的替代分隔符。
答案 1 :(得分:1)
我假设您要切换为使用空定界符而不是_,以提高脚本的可靠性。但是,读取json元素的最安全方法不是使用null分隔符,因为根据RFC7159(page 8)允许使用json文本。例如。如果["a","b","c"]
看起来像["a","b\u0000","c"]
,而您要将空字符附加到每个字符串并使用空定界符来解析它们,则“ b”元素将进入两个单独的bash数组插槽。
相反,考虑到换行总是在json-strings中转义,例如jq -c
我建议依靠规范中的
“字符串以引号开头和结尾。”
考虑到这一点,我们可以定义:
jsonStripQuotes(){ local t0; while read -r t0; do t0="${t0%\"}"; t0="${t0#\"}"; printf '%s\n' "$t0"; done < <(jq '.');}
然后,例如
echo '["a\u0000 b\n","b\nnn","c d"]' | jq .[] | jsonStripQuotes
..应安全地将每个json字符串打印在单独的行上(附加扩展的换行符),并转义字符串中的所有换行符和null。之后,我将IFS设置为仅换行:
while IFS=$'\n' do read -r elem; Arr+=("$elem") ; done < <(echo '["a\u0000 b\n","b\nnn","c d"]' | jq .[] | stripJsonQuotes)
然后如果要用换行符等打印它们,请展开:
printf '%b' "${Arr[*]}"
我相信这是将json字符串解析为bash数组的最可靠方法。
答案 2 :(得分:0)
由于您没有使用jq&#39; $ readarray -t a < <(jq -nc '["a","b","c"][]') ; printf '%s\n' "${a[@]}"
"a"
"b"
"c"
选项,因此问题是标题中提出的问题是否为"XY" problem。如果目标只是将JSON值分配给bash数组,请考虑:
$ readarray -t a < <(jq -nc '["a\\b","\"b\"","c"][]') ; printf '%s\n' "${a[@]}"
"a\\b"
"\"b\""
"c"
请注意,bash数组值是可识别的JSON值(在本例中为JSON字符串,带有双引号)。
更有说服力的是:</ p>
$ readarray -d "" a < <(jq -ncj '["a\\b","\"b\"","c"][]+"\u0000"') ; printf '%s\n' "${a[@]}"
a\b
"b"
c
比较&#34; JSONarity&#34;当使用带有NUL的readarray时会发生这种情况:
angular.forEach($scope.emails, function(email){
if(email.value ===""){
$scope.emails.splice($scope.emails.indexOf(email), 1);
}
});