Fork me on GitHub
#babashka
<
2023-02-23
>
grav07:02:16

I have something working in bash which I'm trying to babashka. Amongst other things, the bash script calls the aws cli like this:

queryId=$(aws logs start-query .... --query-string "$my_query")
where my_query is defined like this:
my_query=$(cat <<-END
  fields @timestamp
  | filter foo=bar
END
)

grav07:02:44

If I just do something like

(def my-query "fields @timestamp
  | filter foo=bar")

(sh (format "aws logs start-query --query-string %s" my-query))
then every token of the query is interpreted as its own argument. I could probably hand-escape the query, and put quotes here and there, but I'm wondering if there's something similar to whatever magic bash does, to have the query be one argument?

lispyclouds07:02:11

you have the " " around $my_query in the bash code. that makes it a single arg

lispyclouds07:02:51

try (format "aws logs start-query --query-string '%s'" my-query)

grav07:02:58

Ah, (format "... --query-string \"%s\"" my-query) seems to do it. I have single-quotes in the "real" query. Thanks @U7ERLH6JX 🙏

2
lispyclouds07:02:46

another way to deal with this which is possibly safer is to use a vec: (sh ["aws" "logs" ... my-query])

grav07:02:54

I see now that the " doesn't really fix the issue with the quotes in the query.

grav07:02:05

I'll try the vector 👍

grav07:02:29

Yes! The vector works, no escaping needed! And it also makes the command easier to read, as I can spare the format, and do line breaks as I please 🙂

lispyclouds07:02:38

been bitten by these things way to often that i almost always use a vec here. youre also making life easier for the shell parser on the other side 😛

grav07:02:19

hehe, and we do want our scripts to go fast 😉

grav07:02:06

That does look scary. And it didn't seem to do what I wanted 😄

lispyclouds07:02:33

it was doing it as expected i think. the bash code shouldve been equally confused

pesterhazy07:02:08

Just pass the args straight into sh without the vector

2
🙌 2
grav07:02:33

ah, the vector is even optional?

grav07:02:40

it's getting better and better.

grav07:02:08

Btw I knew that Paulus would jump into the convo at some point when it was related to bash and escaping 😄

lispyclouds07:02:23

(sh foo bar baz)

pesterhazy07:02:27

Only the first arg is split on spaces

lispyclouds07:02:28

yeah the usecase for the vector is when programmatically building the cmd. something i do often

pesterhazy07:02:54

The vector is old (deprecated?) syntax AFAIK

👍 2
pesterhazy07:02:12

Be free, skip the vec!

lispyclouds07:02:19

yep, its (apply sh args) now

👍 4
grav07:02:40

I'm off vectors in a moment

pesterhazy08:02:27

First arg can optionally be a map with extra goodies

borkdude08:02:41

Btw can you call process/tokenize on the formatted string you had earlier? It should work and if not I’d like to have a bug report. Be sure to upgrade to the newest bb before trying

grav08:02:18

I'll try that @U04V15CAJ and report back here

borkdude08:02:35

Should work with the single quotes around the query that is

grav08:02:06

Pretty sure it'll work, just didn't know what I was looking for 🙂

borkdude08:02:22

Unless the query contains single quotes. In that case you need to wrap the query in escaped double quotes. It should work like in bash.

grav08:02:00

Right 👍 The query does contain single-quotes.

borkdude09:02:42

I think this is a bug:

(prn
 (babashka.process/tokenize "bb -e \"(require '[clojure.set])\""))
["bb" "-e" "(require [clojure.set])\""]
It loses the single quote in the escaped string, which shouldn't happen

borkdude09:02:09

Might not be the same bug as yours but I discovered this while investigating

grav09:02:28

Hm, upgraded bb to latest, tried

(sh (format "aws logs ... --query-string \"%s\"" "query-with-single-quotes 'foo'"))
and it worked out of the box

borkdude09:02:03

yes, there has been a fix around this recently

👍 2
grav09:02:53

Oh, nice! I have no idea how to see what version I upgraded from in Arch Linux, but it does sound like it's related.

borkdude09:02:48

Looks like I was also hitting an old version:

user=> (require '[babashka.process :as p])
nil
user=> (p/tokenize "bb -e \"(require '[clojure.set])\"")
["bb" "-e" "(require '[clojure.set])"]

😌 2
borkdude09:02:16

ah yes, I'm on an old laptop and this fixed it:

==> Upgrading borkdude/brew/babashka
  1.1.172 -> 1.1.173

grav09:02:05

I quite surely did have something that was relatively old. It printed the last expr to std-out, which I remember changed a while ago.

borkdude09:02:46

this changed in 1.1.171

2
grav09:02:16

A patch version with a breaking change 😱 😉

borkdude09:02:56

yes, I should have released 2.1.171 :P

😅 2
lispyclouds09:02:06

well we dont really believe in major versions do we? 😛

borkdude09:02:54

I didn't want to create a python 2.7 controversy

lispyclouds09:02:04

rather major versions = expect upheaval

lispyclouds09:02:16

since python is brought up, the changes that are considered breaking there is almost equal to a bb rewrite. everything else is non-breaking

borkdude11:02:03

Read one character from the console at a time. Works in unix-like terminals.

(require '[babashka.process])

(babashka.process/shell "stty -icanon -echo" )
(println "Echo is off; press `q` to quit.")
(loop []
  (let [k (.read System/in)]
    (println (char k))
    (when (not= k 113)
      (recur))))
(babashka.process/shell "stty icanon echo")
Thanks @elliot for helping figuring this out :)

❤️ 8
👍 2
🎉 4
2
pesterhazy11:02:55

This was easier back in the MSDOS days. You'd just call getch()

pesterhazy11:02:26

... in Borland C

borkdude11:02:38

yes, in gnu c this also works. but Java isn't C

yes 2
borkdude11:02:35

Maybe there is a cross platform way to shell out to a program which reads one character

pesterhazy11:02:24

Bash isn't usually available on windows but bash -c 'read -n1'

borkdude11:02:29

yeah, the bash case would be covered by the above, but Windows is the remaining problem

Bobbi Towers19:02:20

I think rebel readline accomplishes it using jLine. Bruce says it's the only way to do cross platform terminal manipulation

borkdude19:02:37

well, not the only way, since lanterna does it too, but one of the few things that seem to work in JVM world :)

borkdude19:02:05

I noticed the "single character" thing in lanterna relies on the above trick, but in Windows it relies on native hack stuff

dharrigan12:02:25

Co-incidentally, I notice that on babashka.http-client you've added a PUT within the past couple of days. Can I take advantage of this now, or do I need to wait until a new release of babashka?

dharrigan12:02:35

I guess I can add it to a bb.edn/deps.edn and point to the sha

borkdude12:02:53

@U11EL3P9U You can add the http dependncy and use require + :reload

dharrigan12:02:28

works a treat 🙂

🎉 2
Jakub Šťastný16:02:52

How do I check whether I'm in Babashka or in Clojure/JVM?

borkdude16:02:15

You can do so using (System/getProperty "babashka.version")

🙏 2
davesann23:02:52

(def where-am-i? #?(:bb :bb :clj :clj :cljs :cljs))

👍 2
nice 3
clojure-spin 1