LoginSignup
1
1

zsh文字列操作まとめ

Last updated at Posted at 2023-06-24

代入

$ a='こんにちは、世界'

比較

$ if [ "$a" = "hoge" ]; then echo "yes"; fi

別の文字列を含むか

$ if [[ "$a" == *og* ]]; then echo "yes"; fi

長さ

$ echo $#a
8

n文字目を取得(1始まり)

$ echo $a[1]

部分文字列(n文字目から長さl)

$ echo ${a:2:3}
にちは

部分文字列(n文字目からm文字目。終端含む)

$ echo ${c[2,3]}
んに

部分文字列(n文字目以降)

$ echo ${a:2}
にちは、世界

部分文字列(先頭n文字)

$ echo ${a::2}
こん

部分文字列(末尾n文字)

$ echo ${a: -2}
世界

置換(最初の1個)

(検索文字列の*はワイルドカード)

$ a='こんにちは、世界。こんにちは、世界'
$ echo ${a/にち/ばん}
こんばんは、世界。こんにちは、世界

置換(全部)

$ echo ${a//にち/ばん}
こんばんは、世界。こんばんは、世界

前後の空白をtrim

$ c='   Hello world   '
$ echo "[${${c##[[:space:]]##}%%[[:space:]]##}]"
[Hello world]

${c##xxx} で文字列cの先頭からパターンxxxにマッチする部分を削除する(最長マッチ)。
${c%%xxx} で文字列cの末尾からパターンxxxにマッチする部分を削除する(最長マッチ)。
[[:space:]]##はスペースの1個以上の繰り返し(##に1個以上の繰り返しという意味がある)。

先頭の空白をtrim

$ echo "[${c##[[:space:]]##}]"
[Hello world   ]

末尾の空白をtrim

$ echo "[${${c}%%[[:space:]]##}]"
[   Hello  world]

大文字にする

$ b='Hello world'
$ echo ${(U)b}
HELLO WORLD

小文字にする

$ echo ${(L)b}
hello world

ゼロパディング

$ a=1
$ echo ${(l:10::0::0:)a} 
0000000001

splitして配列にする

# カンマで分割
s='hoge,moge,sage'
a=(${(s:,:)s})

# コロンで分割したい場合は、他の記号で囲めば良い(下記はスラッシュにした)
s='hoge:moge:sage'
a=(${(s/:/)s})

# 改行で分割
a=(${(f)s})

# \0で分割
a=(${(0)s})

# zshの文法に従って単語に分割する
a=(${(z)s})

join

リテラルでjoin

$ a=(hoge moge sage)
$ echo ${(j:/:)a}
hoge/moge/sage

変数でjoin

$ a=(hoge moge sage)
$ b='/'
$ echo ${(pj:$b:)a}
hoge/moge/sage

改行でjoin

$ a=(hoge moge sage)
$ echo "${(F)a}"
hoge
moge
sage

正規表現でグルーピング

if [[ "ab123cd456" =~ ([0-9]+)[^0-9]+([0-9]+) ]]; then
    echo "${MATCH}" # => 123cd456
    echo "${match[1]}" # => 123
    echo "${match[2]}" # => 456
fi

パターンマッチ判定

$ [[ "$a" == *og* ]] && echo yes
yes

パターンマッチはglobとは異なり*./にもマッチする。

$ [[ ".zshrc" == * ]] && echo yes 
yes

パターンマッチでは下記の演算子が使える。###のおかげで拡張正規表現相当のことはできる。

*        任意の文字列。空文字列にもマッチ
?        任意の1文字
[abc]    a b c いずれか
[a-z]    aからzまでの1文字
[^abc]   a b c以外の1文字
[^a-z]   aからzまで以外の1文字にマッチ
<1-100>  1から100までの数
<->      任意の数
(...)    パターンのグループ化
x|y      パターンxまたはパターンy
^x       パターンx以外。setopt EXTENDED_GLOBが必要
x~y      パターンxにマッチし、パターンyにマッチしない。setopt EXTENDED_GLOBが必要
x#       パターンxの0回以上の繰り返し。setopt EXTENDED_GLOBが必要。12#は(12)#でなく1(2)#になることに注意
x##      パターンxの1回以上の繰り返し。setopt EXTENDED_GLOBが必要。12#は(12)#でなく1(2)#になることに注意

クォート

バックスラッシュでクォート

$ a='a b"c'                      
$ echo "${(q)a}"
a\ b\"c

シングルクォートでクォート

$ echo "${(qq)a}"
'a b"c'

ダブルクォートでクォート

$ echo "${(qqq)a}"
"a b\"c"

ホームディレクトリを ~ に置換

$ a='/home/aoyama/bin'
$ echo "${(D)a}"
~/bin
$ print -v x -D "/home/aoyama/bin"     
$ echo $x
~/bin

(printは標準出力に出力するコマンドだが、オプション-v xで変数xに代入になる)

~ をホームディレクトリに置換

(e)が使えるが、変数展開やコマンド置換もされてしまうので注意。

$ a='~/bin'
$ echo "${(e)a}"
~/bin

変数が展開される。

$ a='$SHELL'
$ echo "${(e)a}"
/bin/zsh

コマンド置換もされる。

$ a='$(date)'
$ echo "${(e)a}"
Sat Nov  4 12:18:30 AM JST 2023

リテラル

公式ドキュメント:Quoting

シングルクォート

バックスラッシュによるエスケープは一切効かない。

$ print -r -- '\n'   
\n
ダブルクォート

\ ' " $ ! をバックスラッシュでエスケープできる。\n \tは改行・タブにならない。
!のエスケープを忘れて履歴展開されてしまうのはやりがちなので注意)

$ print -r -- "\""
"

ドル付きシングルクォート $'...'

\nで改行、\tでタブ、\xXX でASCIIコード、\uxxxxでユニコードコードポイントなどが使える。

$ print -r -- $'a\nb' 
a
b

$ print -r -- $'\x41'
A

$ print -r -- $'\u3042'
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1