As it stands, there is currently little flexibility in how to convert values to a string.
What I would like is a printf-style function that can format a string based on inputs. I'd imagine something like:
printf(format_str) : Takes a list as input and outputs a string. Each element of the list is used as the input to the respective format character. The list must be the correct length.
For example:
["foo", 3.14159, 2.71828] | printf("Hello %5s, your data is %.2f, %d")
would produce
"Hello foo, your data is 3.14, 2"
Another possible option that would work better with the existing string interpolation might be a function that simply does the tostring conversion with a format spec, like 1|format("02d") == "01".
Then my above example might look more like:
["foo", 3.14159, 2.71828] | "Hello \(.[0]|format("5s")), your data is \(.[1]|format(".2f")), \(.[2]|format("d"))"
I definitely think that, given those two choices, a more typical printf() is the correct route. The string interpolation solves a simpler problem than printf does and I think it is best kept that way.
The question becomes how complete do we want this printf to be? I'm going to strongly advise against passing through to sprintf and friends, as I see a security/safety problem there which merits an amount of consideration. The other side of that, though, is that using sprintf and friends means we can support (essentially) full printf specifiers, assuming we can enforce some kind of type safety.
That being said, I'm all for this. I just think it should be thought through a bit more. @nicowilliams, @pkoppstein, your thoughts?
@wtlangford wrote:
I just think it should be thought through a bit more.
Based in part on @nicowilliams emphasis elsewhere on the virtues of composition, I had assumed that the Tao of Jq would lead to a filter along the lines of the proposed format, at least for floats, which is where the current gap in functionality is most pronounced. This way of doing things is also in line with the way filters are used in web frameworks (see e.g. https://docs.djangoproject.com/en/dev/ref/contrib/humanize/) and meta-frameworks (if AngularJS be such).
Perhaps it's not really an either-or situation, just a question of which comes first?
A printf would be nice, yes, mostly so as to handle alignment and number formatting options.
My need is to be able converting integers into hex representation (that is how I came to this issue).
Looking forward to see printf in next jq version..
Sorry to hijack, but that issue comes up as the "convert to string result", so I decided not to create a new one. Soo how does one currently convert number to string?
@dolzenko: tostring
anyone ending up here might want to look at string interpolation, does 99% of what I'd use printf for: https://stedolan.github.io/jq/manual/#Stringinterpolation-(foo)
@pbkdf3 look at the example in the first post / issue description - it's mostly about various number conversion/formatting options (decimal/hex/scientific, leading zeros/spaces, decimal places, etc.)
A proper printf will have to wait until we have varargs support, whenever that might be. In the meantime you can use string interpolation.
I would like to convert timestamps expressed in milliseconds since the epoch to ISO 8601 strings, with the milliseconds part. jq's built-in time formatting doesn't support milliseconds, so i could use printf, or some more sophisticated string interpolation, to format the milliseconds part, but jq doesn't have that either. One or the other would be really useful!
For my own future reference, i ended up with this:
(.event.timestamp / 1e3 | strftime("%Y-%m-%dT%H:%M:%S")) + ".\(.event.timestamp / 100 % 10)\(.event.timestamp / 10 % 10)\((.event.timestamp) % 10)Z"
Linking to #1341 for further reference.
I'd already be happy to pad a string with spaces to a specified length. Can't find a function for that and printf should be able to do that.
Most helpful comment
My need is to be able converting integers into hex representation (that is how I came to this issue).
Looking forward to see printf in next jq version..