最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

bash - jq: error Cannot index string with string "value" - Stack Overflow

programmeradmin0浏览0评论

Given:

MY_JSON=$(cat <<EOF
{
  "schema": "my.schema",
  "properties": [
    {
      "type": "new.data",
      "value": {
        "labels": {
          "ofasd.io/arch.amd64": "supported",
          "ofasd.io/arch.arm64": "supported",
          "ofasd.io/arch.ppc64le": "supported",
          "ofasd.io/arch.s390x": "unsupported"
        }
      }
    }
  ]
}
EOF
)

I'm trying to filter only "supported" architectures:

arches=$(echo "$MY_JSON" | tr -d '\000-\031' | jq -r '
.properties[] 
| select(.type == "new.data") 
| .value.labels 
| to_entries 
| map(select(.key | test("^ofasd\\.io/arch\\.") and .value == "supported")) 
| map(.key | sub("^ofasd\\.io/arch\\."; "")) 
| join("\n")')

Expected output:

amd64
arm64
ppc64le

Actual output:

jq: error (at <stdin>:0): Cannot index string with string "value"

Could someone please help me understand what I'm doing wrong? It seems like the issue is that ofasd.io/arch.* filtering is not working. When I run:

echo "$MY_JSON" | jq -r '
.properties[] 
| select(.type == "new.data") 
| .value.labels 
| to_entries 
| map(select(.key | test("^ofasd.io/arch\\.") and .value == "supported"))'

I get:

echo "$MY_JSON" | jq -r '' failed with status 5

Given:

MY_JSON=$(cat <<EOF
{
  "schema": "my.schema",
  "properties": [
    {
      "type": "new.data",
      "value": {
        "labels": {
          "ofasd.io/arch.amd64": "supported",
          "ofasd.io/arch.arm64": "supported",
          "ofasd.io/arch.ppc64le": "supported",
          "ofasd.io/arch.s390x": "unsupported"
        }
      }
    }
  ]
}
EOF
)

I'm trying to filter only "supported" architectures:

arches=$(echo "$MY_JSON" | tr -d '\000-\031' | jq -r '
.properties[] 
| select(.type == "new.data") 
| .value.labels 
| to_entries 
| map(select(.key | test("^ofasd\\.io/arch\\.") and .value == "supported")) 
| map(.key | sub("^ofasd\\.io/arch\\."; "")) 
| join("\n")')

Expected output:

amd64
arm64
ppc64le

Actual output:

jq: error (at <stdin>:0): Cannot index string with string "value"

Could someone please help me understand what I'm doing wrong? It seems like the issue is that ofasd.io/arch.* filtering is not working. When I run:

echo "$MY_JSON" | jq -r '
.properties[] 
| select(.type == "new.data") 
| .value.labels 
| to_entries 
| map(select(.key | test("^ofasd.io/arch\\.") and .value == "supported"))'

I get:

echo "$MY_JSON" | jq -r '' failed with status 5
Share Improve this question edited Mar 3 at 17:33 Barbaros Özhan 65.6k11 gold badges36 silver badges61 bronze badges asked Mar 3 at 16:48 anechkayfanechkayf 5671 gold badge8 silver badges16 bronze badges 3
  • What's the intent behind the tr -d? You can't have any NULs in the input, and other very-low-ASCII values mostly wouldn't be valid JSON unless escaped. – Charles Duffy Commented Mar 3 at 17:04
  • For sanity's sake, also replace MY_JSON=$(cat <<EOF {…} EOF) with my_json='{…}' (but with all the newlines still included, I just had to leave them out in this comment). – pmf Commented Mar 3 at 17:05
  • The JSON format allows arbitrary space characters and newlines between tokens. There is no need to remove the new line characters before passing the JSON to jq. – axiac Commented Mar 3 at 17:07
Add a comment  | 

2 Answers 2

Reset to default 3

In select(.key | test("^ofasd\\.io/arch\\.") and .value == "supported"), you dive into .key, make your test (which, btw, could be simplified to startswith("ofasd.io/arch.")), but then there's no .value (inside .key) anymore. Wrap it in parens to keep the context: select((.key | test("^ofasd\\.io/arch\\.")) and .value == "supported")

Here's a simplified version

.properties[]
| select(.type == "new.data")
| .value.labels
| to_entries[]
| select(.value == "supported").key
| scan("^ofasd\\.io/arch\\.\\K.*")
amd64
arm64
ppc64le

Demo

The pipe operator (|) has higher precedence than you think and the condition in map(select(...)) is evaluated in a different way that you want.

You can fix it by wrapping .key | test("^ofasd\\.io/arch\\.") in parenthesis.

Instead of join("\n") I would use the array iterator (.[]). Combined with command line option -r (raw output), it produces the output that you expect.

.properties[] 
| select(.type == "new.data") 
| .value.labels 
| to_entries 
| map(select((.key | test("^ofasd\\.io/arch\\.")) and .value == "supported")) 
| map(.key | sub("^ofasd\\.io/arch\\."; ""))
| .[]

If you apply the iterator earlier, after to_entries, there is no need for map() any more:

.properties[] 
| select(.type == "new.data") 
| .value.labels 
| to_entries[]
| select((.key | test("^ofasd\\.io/arch\\.")) and .value == "supported")
| .key
| sub("^ofasd\\.io/arch\\."; "")

You can see it working on this JQ playground.

发布评论

评论列表(0)

  1. 暂无评论