Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature request] A raw, non-stdout output channel #2592

Closed
benblank opened this issue May 24, 2023 · 3 comments
Closed

[Feature request] A raw, non-stdout output channel #2592

benblank opened this issue May 24, 2023 · 3 comments

Comments

@benblank
Copy link

benblank commented May 24, 2023

Use case

I recently wrote a script which selects specific records and thought it would be nice to print a message for the user indicating how many matching records had been found. However, I was not able to find a way to produce raw output which was not sent to stdout (and therefore included in the script's normal output).

Effectively, I was hoping for something like the following:

$ jq '.log.entries
  | [ .[]
    | select(.request.url | startswith("https://five35.com/api/foo"))
    | { request: .request, response: .response } ]
  | ("Found \(length) matching request(s)." | magic_output_function)
  , .' requests.har > api-requests.json
Found 100 matching request(s).
$ head -n 2 api-requests.json
[
    {

The closest match for magic_output_function I could find was stderr | empty, which unfortunately prints its output as a JSON-formatted string, making it unsuitable for user-friendly output.

Requested feature

Ideally, I'd love to see a function which could send arbitrary output to arbitrary file descriptors. For example:

write_fd(fd)

The write_fd function writes a string from its input to the specified file descriptor. The only valid input is a single string, which is written in raw fashion. Note that file descriptor 1 (stdout) is where jq's normal output is sent.

This function could then be combined with any number of existing jq features to create any form of output desired, even duplicating the behavior of debug/0 and stderr/0.

# Write any value to stderr as a complete line, producing no results.
def println: "\(.)\n" | write_fd(2);

# Log a value to an extra file descriptor, which the user can redirect to wherever they like. The input
# is also the result, so that logging may be inserted into a pipeline
def log: ("\(tojson)\n" | write_fd(4)), .;

# Log all input elements as a JSON stream and print the number of selected elements before writing output.
[ .[] | log | select(.accountName == ("\(.firstName).\(.lastName)" | ascii_downcase)) ]
| ("Found \(length) match(es)." | println), .
@itchyny
Copy link
Contributor

itchyny commented Jul 31, 2023

The stderr filter now prints the string in raw format since the manual states it should do so (fixed by #2751). The proposed solution is an unportable and very complex way of solving the issue, and we will unlikely to implement such feature. Print log messages to standard error, and filter the output if you need.

@itchyny itchyny closed this as completed Jul 31, 2023
@itchyny itchyny closed this as not planned Won't fix, can't repro, duplicate, stale Jul 31, 2023
@nicowilliams
Copy link
Contributor

See also the dlopen branch.

@benblank
Copy link
Author

benblank commented Jul 31, 2023

While I do still think a more general output function would be handy, having raw output from stderr certainly covers all the actual use cases I have (and, I would expect, nearly all reasonable use cases).

Many thanks for the change! I'll anticipate 1.7 eagerly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants