Clojure 文字列操作ライブラリ - cuerdas
Clojure/Clojurescript の文字列操作のユーティリティを提供するライブラリ cuerdas
を一通り全部試す。なんとなくの挙動はイメージできるけど、こういうときどうだっけをいつも忘れて毎回試してるので備忘がてら。
全部やるつもりだったが多過ぎてやめた。残りはまたそのうち更新して追記する。
- GitHub funcool/cuerdas: String manipulation library for Clojure(Script)
- API Docs https://funcool.github.io/cuerdas/latest/
テストコードも見れば?
準備
Leiningen の新しいプロジェクトを作って、依存を追加して、 REPL を起動。
$ lein new hi-cuerdas
$ lein cd hi-cuerdas
$ vi project.clj # [funcool/cuerdas "2022.03.27-397"] を :dependencies に追加
$ lein repl
cuerdas.core
名前空間
require する。
いくつか clojure.core
ns の関数と同じ名前の関数があるので 警告 が出る。
reverse
, format
, empty?
, concat
, unquote
, keyword
, chars
, repeat
user=> (require '[cuerdas.core :refer :all])
WARNING: reverse already refers to: #'clojure.core/reverse in namespace: user.core, being replaced by: #'cuerdas.core/reverse
WARNING: format already refers to: #'clojure.core/format in namespace: user.core, being replaced by: #'cuerdas.core/format
WARNING: empty? already refers to: #'clojure.core/empty? in namespace: user.core, being replaced by: #'cuerdas.core/empty?
WARNING: replace already refers to: #'clojure.core/replace in namespace: user.core, being replaced by: #'cuerdas.core/replace
WARNING: concat already refers to: #'clojure.core/concat in namespace: user.core, being replaced by: #'cuerdas.core/concat
WARNING: unquote already refers to: #'clojure.core/unquote in namespace: user.core, being replaced by: #'cuerdas.core/unquote
WARNING: keyword already refers to: #'clojure.core/keyword in namespace: user.core, being replaced by: #'cuerdas.core/keyword
WARNING: chars already refers to: #'clojure.core/chars in namespace: user.core, being replaced by: #'cuerdas.core/chars
WARNING: repeat already refers to: #'clojure.core/repeat in namespace: user.core, being replaced by: #'cuerdas.core/repeat
nil
ちなみに cuerdas.core
以外に cuerdas.regexp
もあり、cljs 向けに少数の 正規表現ヘルパー関数がある。
早見表
-
文字列構成の判定
-
empty?
空文字列か -
empty-or-nil?
空文字列 or nil か -
blank?
空文字列 or 空白文字 のみか -
alpha?
アルファベット文字のみか -
letters?
alpha? のユニコード対応版 -
alnum?
アルファベット文字 or 数字 のみか -
word?
alnum? のユニコード対応版 -
numeric?
数値を表す文字のみか(負の数や少数を含める) -
digits?
数値を表す文字のみか(負の数や少数を含めない) -
starts-with?
特定の文字列で始まるか -
ends-with?
特定の文字列で終わるか -
includes?
特定の文字列を含むか -
one-of?
includes? の第二引数が Charactor 型版?
-
-
記法変換
-
pascal
パスカルケース(区切りで大文字かつ先頭が大文字:FooBarBaz
)に変換 -
camel
キャメルケース(区切りで大文字かつ先頭が小文字:fooBarBaz
)に変換 -
snake
スネークケース(アンダーバー区切り:foo_bar_baz
)に変換 -
kebab
ケバブケース(ハイフン区切り:foo-bar-baz
)に変換 -
human
ヒューマンケース?(半角スペース区切り:foo bar baz
)に変換 -
title
タイトルケース?(半角スペース区切りで各単語の先頭が大文字:Foo Bar Baz
)に変換 -
phrase
フレーズケース?(半角スペース区切りで最初の単語の先頭のみ大文字:Foo bar baz
)に変換 -
css-selector
CSS のセレクタ形式(-foo-bar-baz
orfoo-bar-baz
)に変換 -
js-selector
Javascript のセレクタ形式(FooBarBaz
orfooBarBaz
)に変換
-
-
大文字小文字変換
-
lower
全ての文字を小文字に変換 -
upper
全ての文字を大文字に変換 -
capital
先頭の文字を大文字に変換
-
-
フォーマット
-
istr
ES6 の Template Strings に近い文字列フォーマット。~{value}
-
ffmt
Clojure の匿名関数に近い文字列フォーマット。%
,%1
,%2
... -
fmt
format のエイリアス -
format
C言語などの format 関数に近い文字列フォーマット。%s
or$1
,$2
...
-
-
空白や文字列の除去
-
trim
文字列の前後から空白文字かあるいは指定した文字を取り除く -
ltrim
trim
の先頭側だけ版。 -
rtrim
trim
の末尾側だけ版。 -
strip
trim
のエイリアス -
lstrip
ltrim
のエイリアス -
rstrip
rtrim
のエイリアス -
strip-newlines
改行を半角スペースに変換する -
strip-prefix
文字列から接頭辞文字列を取り除く -
strip-suffix
文字列から接尾辞文字列を取り除く -
strip-tags
文字列から HTML タグを取り除く -
clean
先頭と末尾の whitespaces は取り除き、それ以外の連続する whitespaces を1つの半角スペースに変換する。 -
collapse-whitespace
隣接する空白文字を半角スペースに変換する
-
-
分割
-
chars
文字列を1文字ずつの文字列に分割する -
words
文字列を単語に分割する -
lines
文字列を改行で分割する -
split
文字列を指定した個数に分割する。デフォルトは空白文字ですべて分割する。
-
-
結合
-
concat
clojure.core/str
関数のマクロ版。マクロにしたことで性能がよくなるケースがある。 -
join
指定したセパレータで結合した文字列を作る -
unlines
改行で結合する。lines
の逆。
-
-
インデックス
-
index-of
指定した文字列が最初に現れるインデックスを返す -
last-index-of
指定した文字列が最後に現れるインデックスを返す
-
-
その他変換
-
<<
istr
の後方互換性のために残されている。 -
<<-
インデントをコード上での見た目と同じような感じにしてくれる。 -
escape-html
HTML の特殊文字をエスケープする。 -
unescape-html
escape-html
の逆 -
keyword
clojure.core/keyword
のより柔軟なバージョン -
to-bool
True っぽい文字列を Boolean のtrue
に変換。 -
pad
指定した文字列の数に足りるまでパディングする。 -
prune
文字列を指定された長さに刈り取る -
surround
文字列を別の文字列で囲む。 -
unsurround
surround
の逆の操作 -
quote
文字列を"
で囲む -
unquote
quote
の逆の操作 -
stylize
英語の文章文字列を統一的に整形する repeat
replace
replace-first
reverse
slice
slug
substr-between
uslug
-
文字列構成の判定
empty?
文字列が空か。
empty-or-nil?
と比較すると nil の場合が違うだけ。
user=> (empty? nil)
false
user=> (empty? "")
true
user=> (empty? " ")
false
user=> (empty? "foo")
false
参考: clojure.core/empty?
は Collection 一般に使う関数。
user=> (clojure.core/empty? " ")
false
user=> (clojure.core/empty? "")
true
user=> (clojure.core/empty? [])
true
user=> (clojure.core/empty? {})
true
user=> (clojure.core/empty? '())
true
user=> (clojure.core/empty? #{})
true
user=> (clojure.core/empty? nil)
true
ちなみに clojure.core/empty? のほうは seq との使い分けがあるで注意。
user=> (clojure.repl/doc clojure.core/empty?)
-------------------------
clojure.core/empty?
([coll])
Returns true if coll has no items - same as (not (seq coll)).
Please use the idiom (seq x) rather than (not (empty? x))
empty-or-nil?
文字列が空または nil か。
user=> (empty-or-nil? nil)
true
user=> (empty-or-nil? "")
true
user=> (empty-or-nil? " ")
false
user=> (empty-or-nil? "foo")
false
blank?
文字列が空か whitespaces / 空白文字 かどうか。
user=> (blank? nil)
false
user=> (blank? "")
true
user=> (blank? " ")
true
user=> (blank? " a ")
false
user=> (blank? " あ ")
false
; 全角スペースもいける。
user=> (blank? " ")
true
; ちなみに全角スペースはコードポイントで表すと U+3000
user=> (blank? (str \u3000))
true
; もちろん文字列型でないとだめ
user=> (blank? \u3000)
false
; 改行文字なども含まれる
user=> (blank? "\n\t")
true
user=> (blank? (str \space \newline \formfeed \return \tab))
true
; ただし backspace は含まれない
user=> (blank? (str \backspace))
false
alpha?
alphabet / アルファベット かどうか。
user=> (alpha? nil)
false
user=> (alpha? "")
false
user=> (alpha? "Foo")
true
user=> (alpha? "Foo Bar")
false
; 全角はとうぜん false
user=> (alpha? "Foo")
false
letters?
alpha?
のユニコード対応バージョン。
; return false
user=> (letters? nil)
false
user=> (letters? "")
false
user=> (letters? " ")
false
user=> (letters? "Foo1")
false
user=> (letters? "Foo ")
false
; return true
user=> (letters? "Foo")
true
user=> (letters? "Русский")
true
; 参考比較
user=> (alpha? "Русский")
false
alnum?
alphanumeric (アルファベットあるいは数)の文字列かどうか。
user=> (alnum? nil)
false
user=> (alnum? "")
false
user=> (alnum? "Foo123")
true
user=> (alnum? "Foo 123")
false
; 文字列型じゃないと問答無用で false
user=> (alnum? 123)
false
user=> (alnum? "123")
true
; 全角はとうぜん false
user=> (alnum? "Foo123")
false
user=> (alnum? "Foo123")
false
word?
alnum?
のユニコード対応バージョン。
user=> (word? nil)
false
user=> (word? "")
false
user=> (word? "Foo123")
true
user=> (word? "Foo 123")
false
user=> (word? "Русский123")
true
; 参考比較
user=> (alnum? "Русский123")
false
numeric?
文字列が 数値 のみで構成されるか。
少数や負の数の表記を true とするあたりが digits?
との違い。
; return true
user=> (numeric? "123")
true
user=> (numeric? "0123")
true
user=> (numeric? "-123.04") ; 負の数や少数
true
user=> (numeric? "2e10")
true
; return false
user=> (numeric? nil)
false
user=> (numeric? 10)
false
user=> (numeric? :hoge)
false
user=> (numeric? "")
false
user=> (numeric? "-123.04 ") ; スペース入り
false
user=> (numeric? "1/2") ; 分数
false
digits?
文字列が digit のみで構成されるか。
; return true
user=> (digits? "123")
true
user=> (digits? "0123")
true
; return false
user=> (digits? nil)
false
user=> (digits? 10)
false
user=> (digits? :hoge)
false
user=> (digits? "") ; 空文字
false
user=> (digits? " 123 ") ; スペース入り
false
user=> (digits? "-123") ; 負の数
false
user=> (digits? "123.4") ; 少数
false
user=> (digits? "1/2") ; 分数
false
starts-with?
; return true
ser=> (starts-with? "FooBar" "Foo")
true
user=> (starts-with? "FooBar" "F")
true
user=> (starts-with? "FooBar" "")
true
user=> (starts-with? "" "")
true
; return false
user=> (starts-with? "FooBar" "Baz")
false
; どっちかの引数が nil だと結果は必ず false
user=> (starts-with? "" nil)
false
user=> (starts-with? nil "")
false
; 一文字だとしても Character 型は Exception に。
user=> (starts-with? "FooBar" "Baz")
false
user=> (starts-with? "FooBar" \F)
Execution error (UnsupportedOperationException) at cuerdas.core/starts-with? (core.cljc:127).
count not supported on this type: Character
; 数値型は通るけど暗黙でキャストされたりはしない。
user=> (starts-with? "1FooBar" 1)
false
ends-with?
第一引数の文字列が、第二引数の文字列を接尾辞として持つか。
; return true
user=> (ends-with? "FooBar" "Bar")
true
user=> (ends-with? "FooBar" "r")
true
user=> (ends-with? "FooBar" "")
true
user=> (ends-with? "" "")
true
: return true
user=> (ends-with? "FooBar" "Baz")
false
; どっちかの引数が nil だと結果は必ず false
user=> (ends-with? "" nil)
false
user=> (ends-with? nil "")
false
; 一文字だとしても Character 型は Exception に。
user=> (ends-with? "FooBar" \r)
Execution error (UnsupportedOperationException) at cuerdas.core/ends-with? (core.cljc:138).
count not supported on this type: Character
; 数値型は通るけど暗黙でキャストされたりはしない。
user=> (ends-with? "FooBar1" 1)
false
includes?
第一引数の文字列に第二引数の文字列が含まれているか。
user=> (includes? "" "")
true
user=> (includes? "FooBar" "oB")
true
user=> (includes? "FooBar" "")
true
; 引数のどっちかが nil だと false
user=> (includes? "" nil)
false
user=> (includes? nil "")
false
one-of?
includes? の第二引数が Charactor 型版?
文字列型で渡してもエラーにならずだまって false になるし includes? で十分なように思える。
;
user=> (one-of? "FooBar" \o)
true
user=> (one-of? "FooBar" \x)
false
user=> (one-of? "FooBar" "o") ; Charactor 型ではなく文字列型の場合
false
user=> (one-of? "FooBar" "")
false
user=> (one-of? "" "")
false
記法変換
pascal
パスカルケース(区切りで大文字かつ先頭が大文字)に変換する。
user=> (pascal "FooBarBaz") ; from pascal
"FooBarBaz"
user=> (pascal "fooBarBaz") ; from camel
"FooBarBaz"
user=> (pascal "foo_bar_baz") ; from snake
"FooBarBaz"
user=> (pascal "foo-bar-baz") ; from kebab
"FooBarBaz"
user=> (pascal "foo bar baz") ; from human
"FooBarBaz"
; それらが混ぜって、複数で、先頭や末尾にも区切り文字があるパターン
user=> (pascal " __--Foo __--Bar __--baz __--")
"FooBarBaz"
; return nil
user=> (pascal nil)
nil
user=> (pascal "")
nil
user=> (pascal " _-")
nil
; 全角アルファベットも OK
user=> (pascal "aaa bbb-ccc_ddd")
"AaaBbbCccDdd"
; 全角ひらがなや半角カナはとうぜんだめ
user=> (pascal "ぁああぃいい")
"ぁああぃいい"
user=> (pascal "ァアアィイイ")
"ァアアィイイ"
; keyword
user=> (pascal :foo-Bar_baz)
"FooBarBaz"
camel
キャメルケース(区切りで大文字かつ先頭が小文字)に変換する。
user=> (camel "FooBarBaz") ; from pascal
"fooBarBaz"
user=> (camel "fooBarBaz") ; from camel
"fooBarBaz"
user=> (camel "foo_bar_baz") ; from snake
"fooBarBaz"
user=> (camel "foo-bar-baz") ; from kebab
"fooBarBaz"
user=> (camel "foo bar baz") ; from human
"fooBarBaz"
; return nil
user=> (camel nil)
nil
user=> (camel "")
nil
user=> (camel " _-")
nil
; 全角アルファベットも OK
user=> (camel "aaa bbb-ccc_ddd")
"aaaBbbCccDdd"
; 全角ひらがなや半角カナはとうぜんだめ
user=> (camel "ぁああぃいい")
"ぁああぃいい"
user=> (camel "ァアアィイイ")
"ァアアィイイ"
; keyword
user=> (camel :foo-Bar_baz)
"fooBarBaz"
snake
スネークケース(アンダーバー区切り)に変換する。
user=> (snake "FooBarBaz") ; from pascal
"foo_bar_baz"
user=> (snake "fooBarBaz") ; from camel
"foo_bar_baz"
user=> (snake "foo_bar_baz") ; from snake
"foo_bar_baz"
user=> (snake "foo-bar-baz") ; from kebab
"foo_bar_baz"
user=> (snake "foo bar baz") ; from human
"foo_bar_baz"
; それらが混ぜって、複数で、先頭や末尾にも区切り文字があるパターン
user=> (snake " __--Foo __--Bar __--baz __--")
"foo_bar_baz"
; return nil
user=> (snake nil)
nil
user=> (snake "")
nil
user=> (snake " _-")
nil
; keyword
user=> (snake :foo-Bar_baz)
"foo_bar_baz"
kebab
ケバブケース(ハイフン区切り)に変換する。
user=> (kebab "FooBarBaz") ; from pascal
"foo-bar-baz"
user=> (kebab "fooBarBaz") ; from camel
"foo-bar-baz"
user=> (kebab "foo_bar_baz") ; from snake
"foo-bar-baz"
user=> (kebab "foo-bar-baz") ; from kebab
"foo-bar-baz"
user=> (kebab "foo bar baz") ; from human
"foo-bar-baz"
; それらが混ぜって、複数で、先頭や末尾にも区切り文字があるパターン
user=> (kebab " __--Foo __--Bar __--baz __--")
"foo-bar-baz"
; return nil
user=> (kebab nil)
nil
user=> (kebab "")
nil
(kebab " _-")
nil
; keyword
user=> (kebab :foo-Bar_baz)
"foo-bar-baz"
human
シングル半角スペース区切りに変換する。
user=> (human "FooBarBaz") ; from pascal
"foo bar baz"
user=> (human "fooBarBaz") ; from camel
"foo bar baz"
user=> (human "foo_bar_baz") ; from snake
"foo bar baz"
user=> (human "foo-bar-baz") ; from kebab
"foo bar baz"
user=> (human "foo bar baz") ; from human
"foo bar baz"
; それらが混ぜって、複数で、先頭や末尾にも区切り文字があるパターン
user=> (human " __--Foo __--Bar __--baz __--")
"foo bar baz"
; return nil
user=> (human nil)
nil
user=> (human "")
nil
user=> (human " _-")
nil
; keyword
user=> (human :foo-Bar_baz)
"foo bar baz"
title
シングル半角スペース区切りかつ各単語の先頭を大文字に変換する。
user=> (title "FooBarBaz") ; from pascal
"Foo Bar Baz"
user=> (title "fooBarBaz") ; from camel
"Foo Bar Baz"
user=> (title "foo_bar_baz") ; from snake
"Foo Bar Baz"
user=> (title "foo-bar-baz") ; from kebab
"Foo Bar Baz"
user=> (title "foo bar baz") ; from human
"Foo Bar Baz"
; それらが混ぜって、複数で、先頭や末尾にも区切り文字があるパターン
user=> (title " __--Foo __--Bar __--baz __--")
"Foo Bar Baz"
; return nil
user=> (title nil)
nil
user=> (title "")
nil
user=> (title " _-")
nil
; keyword
user=> (title :foo-Bar_baz)
"Foo Bar Baz"
phrase
シングル半角スペース区切りかつ最初の単語のみ先頭を大文字に変換する。
user=> (phrase "FooBarBaz") ; from pascal
"Foo bar baz"
user=> (phrase "fooBarBaz") ; from camel
"Foo bar baz"
user=> (phrase "foo_bar_baz") ; from snake
"Foo bar baz"
user=> (phrase "foo-bar-baz") ; from kebab
"Foo bar baz"
user=> (phrase "foo bar baz") ; from human
"Foo bar baz"
; それらが混ぜって、複数で、先頭や末尾にも区切り文字があるパターン
user=> (phrase " __--Foo __--Bar __--baz __--")
"Foo bar baz"
; return nil
user=> (phrase nil)
nil
user=> (phrase "")
nil
user=> (phrase " _-")
nil
; keyword
user=> (phrase :foo-Bar_baz)
"Foo bar baz"
css-selector
Javascript のセレクタ形式から CSS のセレクタ形式に変換する。
キャメルケースからケバブケースへの変換に近いけどちょっと違う。
js-selector
の逆。
; 先頭が大文字だと - が付いて、先頭が小文字だと - は付かない。
user=> (css-selector "FooBarBaz")
"-foo-bar-baz"
user=> (css-selector "fooBarBaz")
"foo-bar-baz"
user=> (css-selector " __--Foo __--Bar __--baz __--")
"-foo-bar-baz"
; return nil
user=> (css-selector nil)
nil
user=> (css-selector "")
""
user=> (css-selector " ")
nil
js-selector
CSS のセレクタ形式から Javascript のセレクタ形式に変換する。
ケバブケースからキャメルケースへの変換に近いけどちょっと違う。
css-selector
の逆。
user=> (js-selector "foo-bar-baz")
"fooBarBaz"
user=> (js-selector "-foo-bar-baz")
"FooBarBaz"
user=> (js-selector " __--Foo __--Bar __--baz __--")
"FooBarBaz"
; return nil
user=> (js-selector nil)
nil
user=> (js-selector "")
""
user=> (js-selector " ")
nil
大文字小文字変換
lower
すべて小文字に変換する。
user=> (lower "FooBar")
"foobar"
; 全角アルファベットもいける。
user=> (lower "FooBar") ; 全角アルファベットもいける。
"foobar"
user=> (lower nil)
nil
upper
すべて大文字に変換する。
user=> (upper "FooBar")
"FOOBAR"
; 全角アルファベットもいける。
user=> (upper "FooBar")
"FOOBAR"
user=> (upper nil)
nil
capital
先頭文字を大文字に変える。
user=> (capital "")
""
user=> (capital "a")
"A"
user=> (capital "foo")
"Foo"
user=> (capital "Foo")
"Foo"
user=> (capital " foo")
" foo"
; 全角アルファベットもいける。
user=> (capital "foo")
"Foo"
; 全角ひらがなや半角カナはとうぜんだめ
user=> (capital "ぁぁぁ")
"ぁああ"
user=> (capital "ァァァ")
"ァアア"
user=> (capital nil)
nil
フォーマット
istr
ES6 の Template Strings に近い。
user=> (def value1 111)
#'user/value1
user=> (let [value2 222] (istr "1: ~{value1}, 2: ~{value2}."))
"1: 111, 2: 222."
user=> (let [value1 nil] (istr "1: ~{value1}"))
"1: "
; 対応するシンボルがスコープに存在しない場合は Exception
user=> (let [value2 222] (istr "1: ~{value1}, 2: ~{value2}, 3: ~{value3}."))
Syntax error compiling at (/private/var/folders/d8/y7wwr0wd2q112kpg7b982b7c0000gn/T/form-init18111034881246950275.clj:1:19).
Unable to resolve symbol: value3 in this context
ffmt
文字列フォーマット関数。
istr
の代替で、(コンパイル時に文字列内容が決定できるものは)コンパイル時にフォーマット処理がなされる。内部的に concat
マクロを使っている。
2種類の記法。
- sequential:
%
を並べて順番で対応。 - indexed:
%1
,%2
,%3
, ... でどの変数かも指定。
1. sequential: %
を並べて順番で対応。
; 複数の変数を順に受け取れる。
user=> (ffmt "1:[%], 2:[%]" "1st" "2nd")
"1:[1st], 2:[2nd]"
; 多すぎる引数は無視される。
user=> (ffmt "1:[%], 2:[%]" "1st" "2nd" "3rd")
"1:[1st], 2:[2nd]"
; 逆に使ってる変数の参照の数に対して引数が足りないと Exception
user=> (ffmt "1:[%], 2:[%]" "1st")
Unexpected error (IndexOutOfBoundsException) macroexpanding ffmt at (/private/var/folders/d8/y7wwr0wd2q112kpg7b982b7c0000gn/T/form-init18111034881246950275.clj:1:1).
; 文字列型以外を渡したとき
user=> (ffmt "1:[%], 2:[%] 3:[%]" 111 :two nil)
"1:[111], 2:[:two] 3:[]"
; % 自体を使いたいときは %% と書く。
user=> (ffmt "%1%%" 100)
"100%"
2. indexed: %1
, %2
, %3
, ... でどの変数かも指定。
user=> (ffmt "1:[%2], 2:[%1]" "1st" "2nd")
"1:[2nd], 2:[1st]"
; 引数の変数を全部使用しなくてもいい。
user=> (ffmt "1:[%3], 2:[%3]" "1st" "2nd" "3rd")
"1:[3rd], 2:[3rd]"
; % と %1 は同じ扱い。匿名関数の書き方と一緒。
user=> (ffmt "1:[%], 2:[%1]" "1st" "2nd")
"1:[1st], 2:[1st]"
fmt
format
のエイリアス: (def fmt format)
。ちょっと短く書ける。
format
文字列フォーマット関数。対応する引数が足りない場合(※)に特にエラーにもならずそのままフォーマット文字列が残るのは微妙な気がする。
1. sequential 形式 %s
user=> (format "1:[%s], 2:[%s]" "1st" "2nd" "3rd")
"1:[1st], 2:[2nd]"
; ※
user=> (format "1:[%s], 2:[%s], 3rd:[%s]" 111 nil)
"1:[111], 2:[], 3rd:[%s]"
2. associative 形式 $foo
user=> (format "1:[$a], 2:[$b]" {:a "1st" :b "2nd" :c "3rd"})
"1:[1st], 2:[2nd]"
user=> (format "1:[$a], 2:[$b], 3:[$c]" {:a 111 :b nil})
"1:[111], 2:[], 3:[]"
空白や文字列の除去
trim
文字列の前後から空白文字かあるいは指定した文字を取り除く。
第二引数に指定する除去文字は、文字列ではなく、各文字として扱われる。
user=> (trim " abc ")
"abc"
; 全角スペースは除去されない
user=> (trim " abc ")
" abc "
; 第二引数で除去する文字を明示できる
user=> (trim "-abc-" "-")
"abc"
user=> (trim "--abc--" "-")
"abc"
; 第二引数は文字列としてではなく、1つ1つの文字として除去対象となる。
user=> (trim "::abc_-_" "-_:")
"abc"
user=> (trim "")
""
user=> (trim " ")
""
user=> (trim nil)
nil
ltrim
trim
の先頭側だけ版。
user=> (ltrim " abc ")
"abc "
; 全角スペースは除去されない
user=> (ltrim " abc ")
" abc "
; 第二引数で除去する文字を明示できる
user=> (ltrim "-abc-" "-")
"abc-"
user=> (ltrim "--abc--" "-")
"abc--"
; 第二引数は文字列としてではなく、1つ1つの文字として除去対象となる。
user=> (ltrim "::abc_-_" "-_:")
"abc_-_"
user=> (ltrim "")
""
user=> (ltrim " ")
""
user=> (ltrim nil)
nil
rtrim
trim
の末尾側だけ版。
user=> (rtrim " abc ")
" abc"
; 全角スペースは除去されない
user=> (rtrim " abc ")
" abc "
; 第二引数で除去する文字を明示できる
user=> (rtrim "-abc-" "-")
"-abc"
user=> (rtrim "--abc--" "-")
"--abc"
; 第二引数は文字列としてではなく、1つ1つの文字として除去対象となる。
user=> (rtrim "::abc_-_" "-_:")
"::abc"
user=> (rtrim "")
""
user=> (rtrim " ")
""
user=> (rtrim nil)
nil
strip
trim
のエイリアス: (def strip trim)
lstrip
ltrim
のエイリアス: (def lstrip ltrim)
rstrip
rtrim
のエイリアス: (def rstrip rtrim)
strip-newlines
改行を半角スペースに変換する
user=> (strip-newlines "aaa\nbbb\n")
"aaa bbb "
user=> (strip-newlines "aaa\rbbb\r")
"aaa bbb "
; 複数の連続する改行も単一の半角スペースに変換
user=> (strip-newlines "aaa\n\nbbb\n\n")
"aaa bbb "
user=> (strip-newlines "")
""
user=> (strip-newlines "\n")
" "
user=> (strip-newlines nil)
nil
strip-prefix
文字列から接尾辞文字列を取り除く。
第二引数に指定する文字列と完全に一致した場合のみ取り除かれる。
user=> (strip-prefix "::abcdef::" ":")
":abcdef::"
user=> (strip-prefix "::abcdef::" "::")
"abcdef::"
user=> (strip-prefix "::abcdef::" ":::")
"::abcdef::"
; 第二引数を文字列として完全に一致するかをみるのが lstrip や ltrim との違い
; 参考
user=> (lstrip "::abcdef::" ":")
"abcdef::"
user=> (lstrip "::abcdef::" "::")
"abcdef::"
user=> (lstrip "::abcdef::" ":::")
"abcdef::"
; マッチしない
user=> (strip-prefix "::abcdef::" nil)
"::abcdef::"
user=> (strip-prefix "::abcdef::" "")
"::abcdef::"
user=> (strip-prefix nil "abc")
nil
strip-suffix
文字列から接頭辞文字列を取り除く。
第二引数に指定する文字列と完全に一致した場合のみ取り除かれる。
user=> (strip-suffix "::abcdef::" ":")
"::abcdef:"
user=> (strip-suffix "::abcdef::" "::")
"::abcdef"
user=> (strip-suffix "::abcdef::" ":::")
"::abcdef::"
; 第二引数を文字列として完全に一致するかをみるのが rstrip や rtrim との違い
; 参考
user=> (rstrip "::abcdef::" ":")
"::abcdef"
user=> (rstrip "::abcdef::" "::")
"::abcdef"
user=> (rstrip "::abcdef::" ":::")
"::abcdef"
; マッチしない
user=> (strip-suffix "::abcdef::" nil)
"::abcdef::"
user=> (strip-suffix "::abcdef::" "")
"::abcdef::"
user=> (strip-suffix nil "abc")
nil
strip-tags
文字列から HTML タグを取り除く
user=> (strip-tags "<div>aaaa bbbb</div>")
"aaaa bbbb"
user=> (strip-tags "<div class=\"foo bar\"> aaaa <br /> bbbb </div>")
" aaaa bbbb "
; 特定のタグのみ除去。第二引数はタグを keyword か 文字列で複数指定可能。
user=> (strip-tags "<div> aaaa <br /> bbbb </div>" [:div])
" aaaa <br /> bbbb "
user=> (strip-tags "<div> aaaa <br /> bbbb </div>" ["div"])
" aaaa <br /> bbbb "
user=> (strip-tags "<div> aaaa <br /> bbbb </div>" ["div" "span"])
" aaaa <br /> bbbb "
; タグの個別指定の場合、タグに属性があると反応しない
user=> (strip-tags "<div class='foo bar'> aaaa <br /> bbbb </div>" [:div])
"<div class='foo bar'> aaaa <br /> bbbb "
; 除去ではなく変換も可能
; br タグを改行に変換し、その他のタグは除去。
user=> (strip-tags "<div> aaaa <br /> bbbb </div>" {:br "\n"})
" aaaa \n bbbb "
; br タグを怪猫に変換し、その他のタグは維持。
user=> (strip-tags "<div> aaaa <br /> bbbb </div>" [:br] {:br "\n"})
"<div> aaaa \n bbbb </div>"
; 複数の変換
user=> (strip-tags "<div> aaaa <br /> bbbb </div>" {:br "\n" :div "■"})
"■ aaaa \n bbbb ■"
user=> (strip-tags "<div>aaaa bbbb</div>" nil)
"aaaa bbbb"
user=> (strip-tags "<div>aaaa bbbb</div>" nil nil)
"aaaa bbbb"
user=> (strip-tags nil)
nil
clean
先頭と末尾の whitespaces は取り除き、それ以外の連続する whitespaces を1つの半角スペースに変換する。
user=> (clean " foo\n\nbar \n ")
"foo bar"
user=> (clean "")
""
user=> (clean " ")
""
user=> (clean " ")
""
user=> (clean nil)
nil
user=> (clean 10)
nil
collapse-whitespace
隣接する空白文字を半角スペースに変換する。
clean
との違いがほとんど分からないが、コード見ると使ってる正規表現を含めて実装は異なってる。
用途次第だけど、全角スペースもハンドリングしてくれる clean のほうが使えそう?
user=> (collapse-whitespace " a ")
"a"
user=> (collapse-whitespace " a ")
"a"
user=> (collapse-whitespace " a b")
"a b"
user=> (collapse-whitespace " a b")
"a b"
user=> (collapse-whitespace " foo\n\nbar \n ")
"foo bar"
user=> (collapse-whitespace "")
""
user=> (collapse-whitespace " ")
""
user=> (collapse-whitespace " ")
""
user=> (collapse-whitespace nil)
nil
user=> (collapse-whitespace 10)
nil
分割
chars
1文字ずつに分けたベクタに変換。
user=> (chars nil)
nil
user=> (chars "")
[""]
user=> (chars " ")
[" "]
user=> (chars " ")
[" " " "]
user=> (chars " foo")
[" " "f" "o" "o"]
user=> (chars " あいう")
[" " "あ" "い" "う"]
user=> (chars "foo\nbar")
["f" "o" "o" "\n" "b" "a" "r"]
; 文字列型以外を渡しても例外にはならず nil が返る
user=> (chars :foo)
nil
user=> (chars 12)
nil
; 返り値の型は PersistentVector
user=> (type (chars "foo"))
clojure.lang.PersistentVector
; 返り値の各要素の型は java.lang.String であり java.lang.Character ではない。
user=> (map type (chars "foo"))
(java.lang.String java.lang.String java.lang.String)
words
文字列を単語に分解しベクタに変換する。
user=> (words "Yes, true.")
["Yes" "true"]
user=> (words "it's - no matter how - no problem.")
["it" "s" "-" "no" "matter" "how" "-" "no" "problem"]
; 第二引数で正規表現を直接指定できる。デフォルトは [a-zA-Z0-9_-]+ 。
user=> (words "it's - no matter how - no problem." #"[^-,. ]+")
["it's" "no" "matter" "how" "no" "problem"]
lines
改行で分割する
user=> (lines "foo\nbar\nbaz")
["foo" "bar" "baz"]
; 末尾の改行は無視して取り除かれるが、その他の空行も解釈する。
user=> (lines "\nfoo\n\nbar\n")
["" "foo" "" "bar"]
user=> (lines nil)
nil
split
文字列を指定した個数に分割する。デフォルトは空白文字ですべて分割する。
user=> (split "aaa bbb ccc\nddd ")
["aaa" "bbb" "ccc" "ddd"]
; 分割文字列指定
user=> (split "aaa bbb ccc\nddd " " ")
["aaa" "bbb" "" "ccc\nddd"]
; 分割数も指定
user=> (split "aaa bbb ccc\nddd " " " 0) ; 0 を指定しても意味なし
["aaa" "bbb" "" "ccc\nddd"]
user=> (split "aaa bbb ccc\nddd " " " 1)
["aaa bbb ccc\nddd "]
user=> (split "aaa bbb ccc\nddd " " " 2)
["aaa" "bbb ccc\nddd "]
user=> (split "aaa bbb ccc\nddd " " " 3)
["aaa" "bbb" " ccc\nddd "]
user=> (split "aaa bbb ccc\nddd " " " 4)
["aaa" "bbb" "" "ccc\nddd "]
user=> (split "aaa bbb ccc\nddd " " " 5) ; 4 と変わらず
["aaa" "bbb" "" "ccc\nddd" ""]
; 正規表現で指定も可能
user=> (split "aaa bbb ccc\nddd " #"\s+")
["aaa" "bbb" "ccc" "ddd"]
user=> (split "aaa bbb ccc\nddd " #"\s+" 2)
["aaa" "bbb ccc\nddd "]
user=> (split "")
[""]
user=> (split " ")
[]
user=> (split nil)
nil
結合
concat
clojure.core/str
関数のマクロ版。
cljs ではかなり速く clj でも少し速くなるとのこと。
マクロになったことで clj の場合は連続する文字列インスタンス同士はコンパイル時に結合させてしまうし、 cljs の場合は +
オペレータを使っている。
user=> (concat)
""
user=> (concat nil)
""
user=> (concat "")
""
user=> (concat 123 nil "foo" :abc " ")
"123foo:abc "
; 参考比較。
user=> (str 123 nil "foo" :abc " ")
"123foo:abc "
join
指定したセパレータで結合した文字列を作る
user=> (join ["aaa" "bbb" "ccc"])
"aaabbbccc"
user=> (join " && " ["aaa" "bbb" "ccc"])
"aaa && bbb && ccc"
user=> (join " && " [])
""
user=> (join " && " nil)
""
user=> (join nil ["aaa" "bbb" "ccc"])
"aaabbbccc"
user=> (join "" ["aaa" "bbb" "ccc"])
"aaabbbccc"
; これのつもりで・・・
user=> (join ["aaa" "bbb"])
"aaabbb"
; ・・・これをするミスはありそう
user=> (join "aaa" "bbb")
"baaabaaab"
unlines
改行で結合する。lines
の逆。
user=> (unlines ["aaa" "bbb" nil "ccc"])
"aaa\nbbb\n\nccc"
user=> (unlines ["aaa"])
"aaa"
user=> (unlines [])
""
user=> (unlines nil)
nil
user=> (unlines "")
nil
インデックス
index-of
第一引数の文字列において、第二引数の文字列が登場するインデックスを返す。
user=> (index-of "FooBar" "")
0
user=> (index-of "FooBar" "B")
3
user=> (index-of "FooBar" "Bar")
3
user=> (index-of "FooBar" "Baz")
nil
user=> (index-of nil "")
nil
user=> (index-of "" nil)
nil
last-index-of
マッチする文字列のインデックスを返す。複数マッチする場合は最後にマッチしたところのインデックス。
user=> (last-index-of "foobarbaz" "foo")
0
user=> (last-index-of "foobarbaz foo" "foo")
10
; 参考比較
user=> (index-of "foobarbaz foo" "foo")
0
その他変換
<<
istr
の後方互換性のためにのこされているそう。試してない。
<<-
インデントをコード上での見た目と同じような感じにしてくれる。
; 1行目を除いて最もインデントが少ない行のインデント数をその他の行のインデントから除去する
user=> (println (<<- "aaa
#_=> bbb
#_=> ccc
#_=> ddd
#_=> eee"))
aaa
bbb
ccc
ddd
eee
nil
escape-html
HTML の特殊文字をエスケープする。
; 変化しない
user=> (escape-html "")
""
user=> (escape-html "<>")
"<>"
user=> (escape-html "Foo")
"Foo"
; エスケープされる
user=> (escape-html "<div> & \" </div>")
"<div> & " </div>"
unescape-html
escape-html
の逆
user=> (unescape-html "<div> & " </div>")
"<div> & \" </div>"
user=> (unescape-html "Foo")
"Foo"
user=> (unescape-html "")
""
user=> (unescape-html nil)
nil
keyword
clojure.core/keyword
のより柔軟なバージョン。
user=> (keyword " Foo/Bar_baz qux//--__ ")
:foo-bar-baz-qux
; keyword も受け付ける
user=> (keyword :Foo-Bar_baz)
:foo-bar-baz
; けど / はちょっと特殊な挙動
user=> (keyword :foo/bar)
:bar
; 引数2つにすると第二引数に名前空間を取る。
user=> (keyword "hoge" "foo/Bar_baz qux")
:hoge/foo-bar-baz-qux
user=> (keyword *ns* "foo/Bar_baz qux")
:user/foo-bar-baz-qux
; このあたりは直感的でないかも。
user=> (keyword :hoge "foo/Bar_baz qux")
::hoge/foo-bar-baz-qux
user=> (keyword ":hoge" "foo/Bar_baz qux")
::hoge/foo-bar-baz-qux
user=> (keyword ::hoge "foo/Bar_baz qux")
::user/hoge/foo-bar-baz-qux
user=> (keyword nil "foo/Bar_baz qux")
:/foo-bar-baz-qux
user=> (keyword "" "foo/Bar_baz qux")
:/foo-bar-baz-qux
; return nil
user=> (keyword nil)
nil
user=> (keyword "")
nil
user=> (keyword " ")
nil
to-bool
True っぽい文字列を Boolean の `true` に変換。
大文字小文字は無視される。
; return true
user=> (to-bool "1")
true
user=> (to-bool "on")
true
user=> (to-bool "true")
true
user=> (to-bool "yes")
true
; case-insensitive
user=> (to-bool "Yes")
true
user=> (to-bool "YES")
true
; return false
user=> (to-bool nil)
false
user=> (to-bool "")
false
user=> (to-bool "ok")
false
user=> (to-bool "y")
false
user=> (to-bool "yes ") ; 余計な文字がまざってたらだめ
false
user=> (to-bool 1) ; 数値型はだめ
false
user=> (to-bool '1) ; Character 型もだめ
false
user=> (to-bool "1") ; 全角ももちろんだめ
false
pad
指定した文字列の数に足りるまでパディングする。デフォルトは 半角スペース を 左パディング。
user=> (pad "12" {:length 4})
" 12"
user=> (pad "12" {:length 4 :padding "0"})
"0012"
user=> (pad "12" {:length 4 :padding "0" :type :right})
"1200"
user=> (pad "12" {:length 4 :padding "0" :type :both})
"0120"
; 全角
user=> (pad "12" {:length 4 :padding "零"})
"零零12"
user=> (pad "壱弐" {:length 4 :padding "零"})
"零零壱弐"
; :type :both で padding する数が奇数になるとあまりの1つは left にはいる。
user=> (pad "12" {:length 5 :padding "0" :type :both})
"00120"
; :padding に長さ2以上の文字列を指定しても先頭一文字だけ使われるので注意。
user=> (pad "12" {:length 6 :padding "ab"})
"aaaa12"
; そのまま return される
user=> (pad "12")
"12"
user=> (pad "12" nil)
"12"
user=> (pad "12" {})
"12"
user=> (pad "12" {:length 1}) ; 元の length より短い :length を指定
"12"
user=> (pad "12" {:length 4 :padding 0}) ; :padding は文字列で指定する
"12"
; return nil
user=> (pad 12)
nil
prune
文字列を指定された長さに刈り取る。デフォルトでは末尾に ... が付加される。
; 半角スペースを単語の区切りとして解釈し、単語の途中では切らない
user=> (prune "hi, how are you?" 10) ; hi, how で 6文字
"hi, how..."
user=> (prune "hi, how are you?" 11) ; hi, how are でちょうど 11文字
"hi, how are..."
; デフォルトは末尾に ... が足されるが変更可能
user=> (prune "hi, how are you?" 11 " 以下省略")
"hi, how are 以下省略"
user=> (prune "hi, how are you?" 11 "")
"hi, how are"
user=> (prune "hi, how are you?" 11 nil)
"hi, how are"
; 結果が元の文字数を超える場合は元の文字列を返す
user=> (prune "hi, how are you?" 11 "------")
"hi, how are you?"
user=> (prune "hi, how are you?" 11 "-----")
"hi, how are-----"
user=> (prune "hi, how are you?" 0)
"..."
surround
文字列を別の文字列で囲む。
quote
は第二引数がデフォルトで指定されている。それだけが違い?
user=> (surround "abc" "**")
"**abc**"
user=> (surround "abc" "***")
"***abc***"
user=> (surround "" "**")
"****"
user=> (surround "abc" "")
"abc"
user=> (surround "abc" nil)
"abc"
user=> (surround nil "**")
nil
user=> (surround "abc")
Execution error (ArityException) at user/eval2943 (form-init10559948635999286691.clj:1).
Wrong number of args (1) passed to: cuerdas.core/surround
; 参考
user=> (cuerdas.core/quote "abc")
"\"abc\""
unsurround
surround
の逆の操作。
unquote
は第二引数がデフォルトで指定されている。それだけが違い?
user=> (unsurround "**abc**" "*")
"*abc*"
user=> (unsurround "**abc**" "**")
"abc"
user=> (unsurround "**abc**" "***")
"**abc**"
user=> (unsurround "**abc**" "")
"**abc**"
user=> (unsurround "\"abc\"")
Execution error (ArityException) at user/eval2956 (form-init10559948635999286691.clj:1).
Wrong number of args (1) passed to: cuerdas.core/unsurround
; 参考
user=> (unquote "\"abc\"")
"abc"
quote
文字列を "
で囲む。囲む文字は第二引数で指定可能。
user=> (cuerdas.core/quote "abc")
"\"abc\""
user=> (cuerdas.core/quote "abc" "'")
"'abc'"
user=> (cuerdas.core/quote "abc" "**")
"**abc**"
; そのまま return される
user=> (cuerdas.core/quote "abc" "")
"abc"
user=> (cuerdas.core/quote "abc" nil)
"abc"
user=> (cuerdas.core/quote "")
"\"\""
unquote
quote
の逆の操作。
user=> (unquote "\"abc\"")
"abc"
user=> (unquote "**abc**" "**")
"abc"
user=> (unquote "**abc**" "*")
"*abc*"
user=> (unquote "abc")
"abc"
user=> (unquote "\"abc\"" "")
"\"abc\""
stylize
英語の文章文字列を統一的に整形する。
(stylize s every-fn join-with)
(stylize s first-fn rest-fn join-with)
という形式で、 単語毎に分解し join-with
の文字列を挟ませて結合する。先頭の単語には first-fn
関数を適用し、残りの単語には rest-fn
関数を適用する(あるいは全ての単語に every-fn
関数を適用する)。
文章を統一的にゴリッと整形してきれいにしたいときに使うのかな。日本語だとあまり使いみちはなさそう。
この関数だけテストコードもドキュメントもない。
user=> (stylize " hi, how are you? " #(str "[" % "]") ", ")
"[hi], [how], [are], [you]"
user=> (stylize " hi, how are you? " #(capital %) #(lower %) " ")
"Hi how are you"
user=> (stylize " hi, how are you? " #(capital %) nil " ")
Execution error (NullPointerException) at cuerdas.core/join (core.cljc:477).
Cannot invoke "clojure.lang.IFn.invoke(Object)" because "this.f" is null
repeat
replace
replace-first
reverse
slice
slug
substr-between
uslug
Discussion