swift -e runs code directly from the command line

swift -e runs code directly from the command line

In this blog post, I explain swift -e which is a new command-line option introduced in Swift 5.8 / Xcode 14.3 Beta 1, that allows Swift one-liners.

A Swift one-liner is a line of code written in the Swift programming language that can be executed directly from the command line without creating a separate file.

It is a convenient and efficient way to perform small, one-off tasks or manipulate data.

Motivation

Previously you had to invoke swift from the command line by passing it the filename of a script to run:

swift aProgram.swift

If you wanted to pass the code on the command line, you had to do it awkwardly through Standard Input (stdin)

echo 'print("good")' | swift -

Ruby and Perl provide a nicer way and that's why swift -e was introduced.

Explained: swift -e

In 5.8 the swift command has an option -e to execute a line of code provided on the command line rather than passed through stdin or a source file.

Execute a one-liner

The code itself needs to be between single quotation marks.

swift -e 'print("better")'

Multiple arguments

Multiple -e arguments can be provided.

swift -e 'let x = "best"' -e 'print(x)'

The values of the “-e” switches are each treated as one line of source code, which are concatenated together into a temporary main.swift file and passed to the frontend jobs.

Multiple statements might not be avoidable, especially when using APIs from Foundation for which you need an import statement.

swift -e 'import Foundation' -e 'print(FileManager.default.currentDirectoryPath)'

Multiple statements with a single e argument

I found it easier to separate multiple statements with ;

swift -e 'let x = "best of the best" ; print(x)'

Read standard input in your one-liner

If your Swift one-liner shall process data passed through stdin then you can use the Standard Library function readLine

echo "outsideInput" | swift -e 'readLine() == "outsideInput" ? print("pass") : print("fail")'

Pass textual data to the standard output

Using the Standard Library function print will allow other scripts to consume the information assuming the caller uses pipes to chain commands.

 echo "outsideInput" | swift -e 'readLine() == "outsideInput" ? print("pass") : print("fail")' | xargs echo

The output is the same as in the previous example but I am sure you get my point.

Example: commenting out all code in a Swift file

Here is a more real-life example in which we use standard commands as well as our Swift one-liner to comment out all code in a Swift file.

cat someFile.swift | swift -e 'while let line = readLine() { print("//" + line) }' | tee someFile.swift
  1. cat will read the file content of someFile.swift and we pipe (|) the file content into our Swift one-liner

  2. The Swift one-liner will iterate over the received lines in standard input and writes each line, appending two forward slashes, to standard output

  3. tee reads from the standard input and writes to both standard output (terminal) and into someFile at the same time. Hence the file content gets replaced and we can see the commented-out source code in the terminal.

There might be a more elegant way to do all this but I am not an expert on all the command-line tools on Mac/Linux. So I appreciate that I can combine my little bash/terminal skills and complement them with my Swift knowledge.

Summary

A nifty edition that hopefully expands the use of Swift for scripting.

I am curious if further options/switches will be introduced to match the behavior to ruby, e.g. -n and -p switches as explained here.

Did you find this article valuable?

Support Marco Eidinger by becoming a sponsor. Any amount is appreciated!