3

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?

Biffen
  • 6,249
  • 6
  • 28
  • 36
Jorman Franzini
  • 329
  • 1
  • 3
  • 17

2 Answers2

2

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.

hek2mgl
  • 152,036
  • 28
  • 249
  • 266
  • Thanks, I also tried with .[var] but nothing. This's like an escape, because this's a regex pattern? Also thanks for the side-note. – Jorman Franzini Sep 02 '19 at 20:52
  • np. The `\()` syntax is not a regex syntax. It's plain jq syntax. I've actually never tried how well that plays with the regular expression syntax. The `()` are potentially problematic. Good luck :P – hek2mgl Sep 02 '19 at 21:22
  • ps: if you run into problems, keep in mind that you could also use concatenation: `"foo " + $tosearch + " bar"` – hek2mgl Sep 02 '19 at 21:23
  • 1
    @hek2mgl - The parens are not problematic. Interpolation takes place first. – peak Sep 03 '19 at 06:31
  • Hi, actually I've some problem with ( and or [, I've to better check the output and I've to try the @peak solution – Jorman Franzini Sep 03 '19 at 10:56
  • jesus man ive spent legit 4 hours trying to sort this out and NOWHERE ELSE described how \\($ARG) was the syntax to use in a regex test. @JormanFranzini you need to accept this answer! – vampiire Feb 28 '22 at 23:28
1

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)
peak
  • 105,803
  • 17
  • 152
  • 177
  • Hi @peak, thanks for your suggestion, I've to better check and try your solution. Yes is text but is possible to have ( or [ or dot, I use . to include all over the text. If help maybe is better to clean the input and output text without special char? What do you think? – Jorman Franzini Sep 03 '19 at 11:03
  • what about this: echo "$LISTS" | jq --raw-output --arg TOSEARCH "$TXTIWANT" '.[] | select(.name == "\($TOSEARCH)") | .hash' I just noticed that I already have all json data extracted, so I have the exact name inside the $LISTS – Jorman Franzini Sep 03 '19 at 19:48