zsh strings
Fish has a utility for string maniplulation.
This is how you can do the same things with Zsh builtins.
References:
Length
Get the length of a string with #
.
This is similar to string length
in fish.
$ str="abcdefghijklmnopqrstuvwxyz"
$ echo ${#str}
26
$
Pad/Trim
Left pad a string with the l expansion flag.
Right pad a string with the r expansion flag.
This is similar to string pad
in fish.
$ str="abc"
$ echo ${(l(10)(-))str}
-------abc
$ echo ${(r(10)(ABC))str}
abcABCABCA
$
The docs can be confusing. They show the syntax as l:expr::string1::string2:
, which
uses colons instead of the more readable parens. Don't be confused by the double colon,
which is really just the closing/opening combo )(
. If you choose to follow the docs,
the syntax looks like this:
$ str="abc"
$ echo ${(r:10::-:)str}
abc-------
$
Trim requires the use of sed
. This is similar to string trim
in fish.
$ str=" \t\t\t abc \t\t\t "
$ echo "$str" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
abc
$
Trimming strings other than whitespace can be accomplished with the '#' and '%' parameter expansions.
#
removes at the start of the string. #
is the shortest match, and ##
is the longest.
$ str="a/b/c/d/e/f/g"
$ echo ${str#*/}
b/c/d/e/f/g
$ echo ${str##*/}
g
$
%
removes at the end of the string. %
is the shortest match, and %%
is the longest.
$ str="a/b/c/d/e/f/g"
$ echo ${str%/*}
a/b/c/d/e/f
$ echo ${str%%/*}
a
$
Substring
Get a substing from string with comma indexing [start,end]
.
This is similar to string sub
in fish.
$ str="abcdefghijklmnopqrstuvwxyz"
$ echo ${str[3,6]}
cdef
$
You can also use the ${var:offset:length}
syntax:
$ str="abcdefghijklmnopqrstuvwxyz"
$ echo ${str:3:6}
defghi
$ echo ${str:(-4)}
wxyz
$
Repeat
Repeat a string by using printf
.
This is similar to string repeat
in fish.
$ str="abc"
$ abc3=$(printf "$str%.0s" {1..3})
$ echo $abc3
abcabcabc
$
Escape/Unescape
Escape (quote) strings with the q modifier.
This is similar to string escape
in fish.
$ str="3 tabs \t\t\t."
$ echo "${str:q}"
3\ tabs\ \t\t\t.
$
Unescape (unquote) strings with the Q modifier.
This is similar to string unescape
in fish.
$ str="3 backticks \`\`\`."
$ esc="${str:q}"
$ echo $esc
3\ backticks\ \`\`\`.
$ echo "${esc:Q}"
3 backticks ```.
$
Join/Split
Join strings with the j expansion flag.
This is similar to string join
in fish.
$ words=(abc def ghi)
$ sep=:
$ echo ${(pj.$sep.)words}
abc:def:ghi
$
A common join seperator is the null character.
This is similar to string join0
in fish.
$ words=(abc def ghi)
$ sep="\x00"
$ echo ${${(pj.$sep.)words}:q}
abc\x00def\x00ghi
$
Split strings with the s expansion flag.
This is similar to string split
in fish.
@
: Preserves empty elements. "In double quotes, array elements are put into separate words".p
: Use print syntax. "Recognize the same escape sequences as the print."s
: Split. "Force field splitting at the separator string."
$ str="a:b::c"
$ sep=:
$ printf '%s\n' "${(@ps.$sep.)str}"
a
b
c
$
A common split seperator is the null character.
This is similar to string split0
in fish.
$ str="abc\x00def\x00ghi"
$ sep="\x00"
$ arr=(${(ps.$sep.)str})
$ printf '%s\n' $arr
abc
def
ghi
$
Upper/Lower
Convert a string to uppercase with the u modifier.
This is similar to string upper
in fish.
$ str="AbCdEfGhIjKlMnOpQrStUvWxYz"
$ echo "${str:u}"
ABCDEFGHIJKLMNOPQRSTUVWXYZ
$
Convert a string to lowercase with the l modifier.
This is similar to string lower
in fish.
$ str="AbCdEfGhIjKlMnOpQrStUvWxYz"
$ echo "${str:l}"
abcdefghijklmnopqrstuvwxyz
$
Match/Replace
The zsh/pcre
module allows you to match strings in Zsh.
$ zmodload zsh/pcre
$ str="The following are zip codes: 78884 90210 99513"
$ setopt REMATCH_PCRE
$ [[ $str =~ '\d{5}' ]] && echo "contains zips" || echo "no zips"
contains zips
$
$ zmodload zsh/pcre
$ str="https://gist.github.com/mattmc3/110eca74a876154c842423471b8e5cbb"
$ pattern='^(ftp|https?)://'
$ pcre_compile -smx $pattern
$ pcre_match -b -- $str
$ [[ $? -eq 0 ]] && echo "match: $MATCH, position: $ZPCRE_OP" || echo "no match"
match: https://, position: 0 8
$
Replacing leverages the s modifier. 'g' Means globally.
$ url=https://github.com/zsh-users/zsh-autosuggestions.git
$ url=${url%.git}
$ url=${url:gs/\@/-AT-}
$ url=${url:gs/\:/-COLON-}
$ url=${url:gs/\//-SLASH-}
$ echo $url
https-COLON--SLASH--SLASH-github.com-SLASH-zsh-users-SLASH-zsh-autosuggestions
$
Collect
There are lots of different ways strings need collected. Sometimes you have a string with embedded newlines that you need to split into an array, preserving blanks.
$ str=$(printf '%s\n' four score '' "&" '' seven years ago)
$ echo ${(q-)str}
'four
score
&
seven
years
ago'
$ # remove blanks
$ arr=(${(f@)str})
$ echo $#arr
6
$ # preserve blanks
$ arr=("${(f@)str}")
$ echo $#arr
8
$
Tests
This file passes clitests:
zsh -f -- =clitest --list-run --progress dot --color always zsh-strings.md