Fork me on GitHub

I'd like to use babashka to process a file line by line reading from standard input, but I could not produce the processed lines on the standard output. I've simplified my code to the following to figure out the problem: (ns convert.drop-bart-and-uppercase) (defn clean-location [x] x) (defn clean [lines] (->> lines (map clean-location)) ) (clean *in*) and use the following to execute: cat samples.dat | bb -i -o -f ../convert/src/convert/drop_bart_and_uppercase.clj and here is the sample.dat: Time=Thu Oct 1 15:27:15 PDT 2020, Value=75.7,, Device_Type=tempSensor, Value_Type=Temperature Time=Thu Oct 1 15:28:12 PDT 2020, Value=91.4, Location=a40-tc-ups, Device_Type=UPS, Value_Type=Temperature to my understanding, I'd expect it outputs the identical two lines of the content. But I see nothing. Please help me to figure out my problem. Thanks! ------------ I found the following command works as expected: < samples.dat bb -io '(load-file "/home/yshen/data/temperature-data-archive/convert/src/convert/drop_bart_and_uppercase.clj") (convert.drop-bart-and-uppercase/clean *input*)' but I find it too clumsy to load the file and then call the function


@yubrshen In the first piece of code you use *in* (not *input*) which is not a seq of lines, but just the stdin stream from Clojure.


@borkdude thanks! I wish that I could use *input, how?*


I would like to learn what is the idiomatic way to process every line of string with Babashka?


@yubrshen You can use *input* but this is honestly more for one-liners on the command line. For scripts you might want to use:

$ ls | bb -e "(first (line-seq (io/reader *in*)))"


io/reader is coming from


Thanks. use/input is perfect for my need.


Finally, this is what works for my need.


< samples.dat bb -i -o '(->> *input* (map (fn [line] (clojure.string/replace-first line #"Location=([^.,]+)[^,]+" #(str "Location=" (clojure.string/upper-case (last %1)))))))' I can use user/**input** inside of my script file to access the stdin as list of lines, but I have not figured out how to output lines to stdout inside my script. The above one-liner works, but it's getting hard to maintain. Is there such equivalent mechanism to let babashka to help to output lines to stdout from a script?


I can improve the readability but not keeping in the ecosystem of Clojure:


#!/usr/bin/env bash < $1 bb -i -o '(->> *input* (map (fn [line] (clojure.string/replace-first line #"Location=([^.,]+)[^,]+" #(str "Location=" (clojure.string/upper-case (last %1)))))))'


Is there any better approach, keeping my code mostly in Clojure development environment?


Without babashka in/output flags:

(ns my-script
  (:require [ :as io]
            [clojure.string :as str]))

(defn lines []
  (line-seq (io/reader *in*)))

(->> (lines)
      (fn [line]
        (str/replace-first line #"Location=([^.,]+)[^,]+"
                           #(str "Location=" (str/upper-case (last %1))))))
     (run! println))


This also works with Clojure on the JVM


Yes, exactly, this is what I'm looking for to learn to have the script to run both with Clojure and Babashka. Thanks a million!


@borkdude Thank you again for your help! I have been looking for the idiom to use Babashka to perform sed like streaming editing with Clojure sophistication and simpleness. Finally, I think learned the following:

(ns convert.swap-time
  (:require [ :as io]

(defn sweep
  "Sweep every line from stdio by the function,
  and output to stdout line by line."
  (->> (line-seq (io/reader *in*))
       (map f)
       (run! println)))

(defn move_time_front [line]
   #"^(.+, )(Time=[^,]+, )(.+)$"

(sweep move_time_front)


@yubrshen If you change *in* to *input* in your top program, that should maybe work. If you want to get lines from stdin yourself, you can use (clojure.string/split-lines (slurp *in*)) or (line-seq ( *in*))


ah, I see. yes. *input* is only defined in the user namespace, so you have to use user/*input* in your top program


or get rid of the ns declaration


@borkdude I see. Just use/input Thanks! I may need to have the ns namespace in order to use Clojure's test framework.