Nushell
General
- prefix commands with ^ to use an external command rather than the Nu builtin (ex.
^echo)- all data passed to/from external commands is treated as strings
- Nushell renders lists and tables before passing them to external commands, so to get the raw output use
to text
- Nushell renders lists and tables before passing them to external commands, so to get the raw output use
- all data passed to/from external commands is treated as strings
- instead of using
>to save files, pipe to thesavecommand (ex."hello" | save output.txt) - variable assignment:
let x = $x + 1- variables are immutable, so changes to existing variables are actually shadowing and are block-scoped
- environment changes are block-scoped - for example, using
cdinside a block will only changePWDinside the block, so you don't need to undo thecdbefore the next iteration - wrap pipelines in
()to create subexpressions, which can be spread over multiple lines
(
"01/22/2021" |
parse "{month}/{day}/{year}" |
get year
)
PATH configuration
- PATH is a list of paths at
$env.PATH - To add a new entry, add this to
.env.nu- To find the location of this file, run
echo $nu.env-path
- To find the location of this file, run
$env.PATH = ($env.PATH | split row (char esep) | append '/opt/homebrew/bin')
Data types
- integers
- decimals (includes
Infinity) - strings
''or``strings do no processing (no escapes supported), but can't contain their delimiter character""strings support standard escape characters using\- one-word strings can be written without quotes inside data structures or parameters, but it's better to use quotes
- interpolated strings are wrapped in
$''or$""and use()for expressions- ex.
let name = "Alice"; $"greetings, ($name)" $''doesn't support escapes,$""does- parentheses can be escaped using
\
- ex.
- booleans (
trueorfalse) - dates
date now: get current date- can be coerced to a table:
date now | date to-table
- durations, ex.
2min + 12sec- suffixes:
ns,us,ms,sec,min,hr,day,wk - fractions are supported
- suffixes:
- file sizes, ex.
64mb- supports both
kb(kilobyte, 1000 bytes) andkib(kibibyte, 1024 bytes)
- supports both
- ranges
- inclusive by default:
1..3includes 1, 2, and 3 - to make exclusive:
1..<3includes 1 and 2 - ranges can be open-ended:
..3(0, 1, 2, 3) or3..(3, 4, 5...)- if a range is open-ended on the right side, it will keep counting for as long as possible
- inclusive by default:
- binary
- group of raw bytes, in hex (
0x[FE FF]), binary (0b[1 1010]), or octal (0o[377])
- group of raw bytes, in hex (
null- represents nothing - not the same as the absence of a value, which is marked by ❎
- records
- ex.
{ name: 'Nushell', lang: 'Rust' } - a record is just a one-row table - anything that works on a table row works on a record
transposecan be used to convert records into tables- ex.
{name: sam, rank: 10} | transpose key valueresults in:[{key: name, value: sam}, {key: rank, value: 10}]
- ex.
- ex.
- lists
- ex.
[0 1 'two' 3]- commas are allowed but not required
- a list is just a one-column table - anything that works on a table column works on a list
- ex.
- tables
- ex.
[[x, y]; [12, 15], [8, 9]] - a table is just a list of records, and can be specified that way:
[{ x: 12, y: 15 }, { x: 8, y: 9 }] - rows and columns can be accessed using paths
[{langs:[Rust JS Python], releases:60}].0.langs.2results in:Python- use
?to ~mark access as optional - missing values are replaced withnull- ex.
[{foo: 123}, {}].foo?
- ex.
- a single table row is a record, and a single column is a list
- ex.
- closures
- ex.
{ |e| $e + 1 | into string} - parameters are encased in
|pipes|- for most closures, instead of an explicit parameter you can access the pipeline input using$in - closures can be assigned to variables and run using
do
- ex.
let greet = { |name| print $"Hello ($name)"}
do $greet "Julian"
- blocks
- blocks don't close over variables and can't be passed as values, but can mutate variables in their parent closure
mut x = 1
if true {
$x += 1000
}
print $x
Basic commands
help {command}: get help on a commandhelp commands: list all commandshelp -f {query}: search for help
describe: list the data type of a valueinto {type}: convert a value to a different data type (ex."-5" | into int)do {closure} {params}: run a closureis-empty: determines if a string, list, or table is emptysys: system informationhttp get: fetch the contents of a URL- ex.
http get https://blog.rust-lang.org/feed.xml | table
- ex.
inc {path?}: increment a version number (--major,--minor,--patch)- ex.
open "Cargo.toml" | inc package.version --minor | save "Cargo_new.toml"
- ex.
open {filename}: can parse many different types of files as tables (ex. csv, json, xml, xls(x), sqlite), otherwise loads them as a single string- pass
--rawto always load as a string - to get a table from a SQLite database:
open foo.db | get some_table - to run a SQL query:
open foo.db | query db "select * from some_table"
- pass
save {filename}: write to a file
Working with strings
from {format}: tell Nu to parse a string in the specified format (ex.from json)- use
from csv|tsv|ssvto split comma/tab/space separated data
- use
lines: split string by linessplitsplit row {delimiter}: split into a list by delimitersplit column {delimiter}: split into table columns by delimiter- can pass column names after the delimiter, otherwise generic column names are used
split chars: split into list of characters
parse: split a string into columns'Nushell 0.80' | parse '{shell} {version}'- regex:
'where all data is structured!' | parse --regex '(?P<subject>\w*\s?\w+) is (?P<adjective>\w+)'
str: contains many string functionsstr trim: trim stringstr contains: check for a substring match (or use=~)str index-of {string}str reverse
fill {--width num} {--alignment left|right} {char}: pad a stringsize: get various string statistics (line count, word count, etc)- string comparison operators:
==,!==~,!~: regex comparisons- ex.
'APL' =~ '^\w{0,3}$'
- ex.
starts-with,ends-with- these are operators, not commands!
- use
ansi {color}to color strings- ex.
$'(ansi purple_bold)This text is a bold purple!(ansi reset)' - always end with
ansi reset
- ex.
Working with tables
Tip
Remember that column indices are strings, and row indices are numbers.
-
get {path}: get a list with the values of a table column- ex.
sys | get host- you can pass a nested path, ex.
sys | get host.sessions.name
- you can pass a nested path, ex.
- you can use this to get an index that's in a variable -
let index = 1; $names | get $index
- ex.
-
select {...index}: create a new table with the specified column names or row numbers -
sort-by {column}: sort a table -
length: count rows -
reverse: reverse table row order -
transpose {...colNames}: swap rows and columns -
where {column} {operator} {param}: filter a table- ex.
ls | where size > 1kborps | where cpu > 5 - use
==for equality
- ex.
-
retrieving items:
first {num}andlast {num}: get the first or last num itemstake {num}: get num rows from the beginning- not sure what the difference between
firstandtakeis
- not sure what the difference between
skip {num}: exclude num rows from the beginning- ex.
[red yellow green] | skip 1results in:[yellow green] - since variables are immutable, the table won't be modified unless you explicitly re-assign to it
- ex.
drop {num}: same, but from the endrange: get a range of items[a b c d e f] | range 1..3results in:[b c d]
-
modifying tables:
insert {index} {value}: insert a valueupdate {index} {value}: replace a valueupsert {index} {value}: insert or update, depending on whether the value already existsmove {...index} --after {index}: move one or more rows or columns- or
--before
- or
rename: rename columns- can pass N names to rename the first N columns:
[[a, b]; [1, 2]] | rename foo: column names will befoo, b
- or rename a specific column with
--column[[a, b]; [1, 2]] | rename --column [b bar]: column names will bea, bar
- can pass N names to rename the first N columns:
reject {...index}: drop columnsappend: concatenate two tables with identical column names- ex.
$table1 | append $table2 prepend: same but at the beginning
- ex.
merge: merge two tables (can be chained)- ex.
$table1 | merge $table2 | merge $table3 - you can merge lots of tables by putting them in a list and using reduce:
[$first $second $third] | reduce { |it, acc| $acc | merge $it }
- ex.
Examples
open package.json | get scripts
Working with lists
- conditions:
inandnot-in: operators to check if a value is or isn't in a listany: checks if any item in a list matches a conditionall: same, but checks if every item matches the condition
# Do any color names end with "e"?
$colors | any {|it| $it | str ends-with "e" } # true
- converting lists:
flatten: flattens a single level (call multiple times to flatten deeper)wrap {columnName}: converts a list to a one column table
Iterating over lists
each: the closure gets a parameter with the current list item- use
enumerateto provideindexanditemvalues
- use
par-each: likeeach, but runs in parallel- result order is not guaranteed
let names = [Mark Tami Amanda Jeremy]
$names | each { |it| $"Hello, ($it)!" }
# Outputs "Hello, Mark!" and three more similar lines.
$names | enumerate | each { |it| $"($it.index + 1) - ($it.item)" }
# Outputs "1 - Mark", "2 - Tami", etc.
wherelets you filter the list
let colors = [red orange yellow green blue purple]
$colors | where ($it | str ends-with 'e')
# The block passed to `where` must evaluate to a boolean.
# This outputs the list [orange blue purple].
-
reducetakes a closure that gets 2 parameters, the item and an accumulator- to specify an initial value use
--fold
- to specify an initial value use
let scores = [3 8 4]
$"total = ($scores | reduce { |it, acc| $acc + $it })" # total = 15
$"total = ($scores | math sum)" # easier approach, same result
$"product = ($scores | reduce --fold 1 { |it, acc| $acc * $it })" # total = 96
$scores | enumerate | reduce --fold 0 { |it, acc| $acc + $it.index * $it.item } # 0*3 + 1*8 + 2*4 = 16
Examples
Kill single process by name
- add
-fto force
kill (ps | where name == "Dock" | first).pid
Kill matching processes
ps | where name == "Dock" | each { kill $in.pid }