Home > OS >  Is it possible to insert a variable in Scala string like python format string?
Is it possible to insert a variable in Scala string like python format string?

Time:07-16

I'm trying to create a Scala code that is similar to python where I read a text file such as:

test.sql

 select * from {name}

and insert name variable from the main program itself.

I'm new to Scala but I was able to read the file as such:

val filename = "test.sql"
val src_file = scala.io.Source.fromFile(filename)
val sql_str = try src_file.getLines mkString "\n" finally src_file.close()

Now I'm trying to do something like I would do in Python but in Scala:

sql_str.format(name = "table1")

Is there an equivalent of this in Scala.

CodePudding user response:

Check out the below source, it explains how to use variables within strings just like how we do in python!

https://www.oreilly.com/library/view/scala-cookbook/9781449340292/ch01s05.html

Hope it helps! Happy learning!

CodePudding user response:

I strongly advise against using a string interpolation / replacement to build SQL queries, as it's an easy way to leave your program vulnerable to SQL Injection (regardless of what programming language you're using). If interacting with SQL is your goal, I'd recommend looking into a database helper library like Doobie or Slick.

That disclaimer out of the way, there are a few approaches to string interpolation in Scala.

Normally, string interpolation is done with a string literal in your code, with $... or ${...} used to interpolate expressions into your string (the {} are needed if your expression is more than just a name reference). For example

val name: String = /* ... */
val message = s"Hello, $name"

// bad idea if `table` might come from user input
def makeQuery(table: String) = s"select * from $table"

But this doesn't work for string templates that you load from a file; it only works for string literals that are defined in your code. If you can change things up so that your templates are defined in your code instead of a file, that'll be the easiest way.

If that doesn't work, you could resort to Java's String.format method, in which the template String uses %s as a placeholder for an expression (see the docs for full info on the syntax for that). This related question has an example for using that. This is probably closest to what you actually asked for.

You could also do something custom with string replacement, e.g.

val template: String = /* load from file */
template.replace("{name}", "my_table")

// or something more general-purpose
def customInterpolate(template: String, vars: Map[String, String]): String = {
  vars.foldLeft(template) { case (s, (k, v)) =>
    s.replace(s"{$k}", v)
  }
}
val exampleTmp = s"update {name} set message = {message}"
customInterpolate(exampleTmp, Map(
  "name" -> "my_table",
  "message" -> "hello",
))
  • Related