Jorman Franzini
Jorman Franzini

Reputation: 339

How to pass arguments inside select and test function?

I've this JSON data, extracted from qbittorrent:

[
  {
    "hash": "333333333333333333333333333",
    "name": "testtosearchcaseinsensitive",
    "magnet_uri": "magnet:somedata",
    "size": 1243989552,
    "progress": 1.0,
    "dlspeed": 0,
    "upspeed": 0,
    "priority": 0,
    "num_seeds": 0,
    "num_complete": 2,
    "num_leechs": 0,
    "num_incomplete": 32,
    "ratio": 0.0,
    "eta": "1.01:11:52",
    "state": "stalledUP",
    "seq_dl": false,
    "f_l_piece_prio": false,
    "category": "category",
    "tags": "",
    "super_seeding": false,
    "force_start": false,
    "save_path": "/data/path/",
    "added_on": 1567358333,
    "completion_on": 1567366287,
    "tracker": "somedata",
    "dl_limit": null,
    "up_limit": null,
    "downloaded": 1244073666,
    "uploaded": 0,
    "downloaded_session": 0,
    "uploaded_session": 0,
    "amount_left": 0,
    "completed": 1243989552,
    "ratio_limit": 1.0,
    "seen_complete": 1567408837,
    "last_activity": 1567366979,
    "time_active": "1.01:00:41",
    "auto_tmm": true,
    "total_size": 1243989552,
    "max_ratio": 1,
    "max_seeding_time": 2880,
    "seeding_time_limit": 2880
  },
  {
    "hash": "44444444444444",
    "name": "dontmatch",
    "magnet_uri": "magnet:somedata",
    "size": 2996838603,
    "progress": 1.0,
    "dlspeed": 0,
    "upspeed": 0,
    "priority": 0,
    "num_seeds": 0,
    "num_complete": 12,
    "num_leechs": 0,
    "num_incomplete": 0,
    "ratio": 0.06452786606740063,
    "eta": "100.00:00:00",
    "state": "stalledUP",
    "seq_dl": false,
    "f_l_piece_prio": false,
    "category": "category",
    "tags": "",
    "super_seeding": false,
    "force_start": false,
    "save_path": "/data/path/",
    "added_on": 1566420155,
    "completion_on": 1566424710,
    "tracker": "some data",
    "dl_limit": null,
    "up_limit": null,
    "downloaded": 0,
    "uploaded": 193379600,
    "downloaded_session": 0,
    "uploaded_session": 0,
    "amount_left": 0,
    "completed": 2996838603,
    "ratio_limit": -2.0,
    "seen_complete": 4294967295,
    "last_activity": 1566811636,
    "time_active": "10.23:07:42",
    "auto_tmm": true,
    "total_size": 2996838603,
    "max_ratio": -1,
    "max_seeding_time": -1,
    "seeding_time_limit": -2
  }
]

So I want to match all data where the name have some text, so, in Bash I write this but I can't make it work.

Some declaration to start, actually I pass data via arguments, so I use $1:

TXTIWANT="test"
MYJSONDATA= Here I put my JSON data

Then this jq equation that doesn't work for me is this:

RESULTS=$(echo "$MYJSONDATA" | jq --raw-output --arg TOSEARCH "$TXTIWANT" '.[] | select(.name|test("$TOSEARCH.";"i")) .name')

But I always got an error or all data, I think because $TOSEARCH is not expanded.

Maybe there's a better way to search a string inside a value?

What I do wrong?

Upvotes: 3

Views: 290

Answers (2)

peak
peak

Reputation: 116870

If (as suggested by the name TXTIWANT and by the example, as well as by the wording of the question) the value of "$TXTIWANT" is supposed to be literal text, then using test is problematic, as test will search for a regular expression.

Since it is not clear from the question why you are adding a period to TOSEARCH, in the remainder of this first section, I will ignore whatever requirement you have in mind regarding that.

So if you simply want to find the .name values that contain $TXTIWANT literally (ignoring case), then you could convert both .name and the value of $TXTIWANT to the same case, and then check for containment.

In jq, ignoring the mysterious ".", this could be done like so:



jq --raw-output --arg TOSEARCH "$TXTIWANT" '
  ($TOSEARCH|ascii_upcase) as $up
  | .[]
  | .name
  | select(ascii_upcase|index($up))'

Search for non-terminal occurrence of $TXTIWANT ignoring case

If the "." signifies there must be an additional character after $TXTIWANT, then you could just add another select as follows:

  ($TOSEARCH|length) as $len
  | ($TOSEARCH|ascii_upcase) as $up
  | .[]
  | .name
  | (ascii_upcase|index($up)) as $ix
  | select($ix)
  | select($ix + $len < length)

Upvotes: 1

hek2mgl
hek2mgl

Reputation: 158090

The right syntax for variable (or filter) interpolation with jq looks like this:

"foo \(filter_or_var) bar"

In your case:

jq --raw-output --arg TOSEARCH "$TXTIWANT" '.[]select(.name|test("\($TOSEARCH).";"i")) .name')

side-note: By convention, environment variables (PAGER, EDITOR, ...) and internal shell variables (SHELL, BASH_VERSION, ...) are capitalized. All other variable names should be lower case.

Upvotes: 2

Related Questions