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
cat
will read the file content ofsomeFile.swift
and we pipe (|
) the file content into our Swift one-linerThe Swift one-liner will iterate over the received lines in standard input and writes each line, appending two forward slashes, to standard output
tee
reads from the standard input and writes to both standard output (terminal) and intosomeFile
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 e
dition 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.