サーチ…
構文
- IFSを改行に設定する:IFS = $ '\ n'
- IFSをNULL文字列に設定します。IFS =
- IFSを/文字に設定します。IFS = /
パラメーター
パラメータ | 詳細 |
---|---|
IFS | 内部フィールドセパレータ |
-バツ | コマンドとそれらの引数を実行時に表示する(シェルオプション) |
備考
- ワードスプリットは割り当て中に実行されません。たとえば、
newvar=$var
- 単語の分割は
[[ ... ]]
構文では実行されません - 単語分割を防ぐために変数に二重引用符を使用する
IFSによる分割
もっと明確にするために、 showarg
という名前のスクリプトを作成しましょう。
#!/usr/bin/env bash
printf "%d args:" $#
printf " <%s>" "$@"
echo
さて、違いを見てみましょう:
$ var="This is an example"
$ showarg $var
4 args: <This> <is> <an> <example>
$var
は4つの引数に分割されます。IFS
は空白文字であるため、スペースで単語分割が発生しました
$ var="This/is/an/example"
$ showarg $var
1 args: <This/is/an/example>
IFS
文字が見つからないため、上記の単語分割は行われませんでした。
今度は、 IFS=/
$ IFS=/
$ var="This/is/an/example"
$ showarg $var
4 args: <This> <is> <an> <example>
$var
は1つの引数ではなく4つの引数に分割されています。
何、いつ、そしてなぜ?
シェルがパラメータ拡張 、 コマンド置換 、 変数または算術展開を実行すると、結果内の単語境界をスキャンします。単語境界が見つかった場合、結果はその位置で複数の単語に分割されます。単語境界は、シェル変数IFS
(内部フィールドセパレータ)によって定義されます。 IFSのデフォルト値はスペース、タブ、改行です。つまり、明示的に禁止されていなければ、これら3つの空白文字で単語分割が行われます。
set -x
var='I am
a
multiline string'
fun() {
echo "-$1-"
echo "*$2*"
echo ".$3."
}
fun $var
上記の例では、これはfun
関数がどのように実行されているかです:
fun I am a multiline string
$var
は5つの引数に分割され、I
、am
、a
のみが出力されます。
IFSと単語分割
参照してください何を、いつ、なぜあなたは単語の分割にIFSの所属について知らない場合
IFSをスペース文字のみに設定しましょう:
set -x
var='I am
a
multiline string'
IFS=' '
fun() {
echo "-$1-"
echo "*$2*"
echo ".$3."
}
fun $var
この時間分割はスペース上でのみ機能します。 fun
関数は次のように実行されます:
fun I 'am
a
multiline' string
$var
は3つの引数に分割されます。I
am\na\nmultiline
とstring
が印刷されます
IFSを改行のみに設定しましょう:
IFS=$'\n'
...
今度のfun
は次のように実行されます:
fun 'I am' a 'multiline string'
$var
は3つの引数に分割されます。I am
、 、a
multiline string
印刷されます
IFSをNULL文字列に設定するとどうなるか見てみましょう:
IFS=
...
今回はfun
ことが次のように実行されます:
fun 'I am
a
multiline string'
$var
は分割されていません。すなわち、1つのargのままです。
IFSをnullstringに設定すると、単語の分割を防ぐことができます
単語の分割を防ぐ一般的な方法は、二重引用符を使用することです。
fun "$var"
上記のすべてのケースで単語の分割を防止します。つまり、 fun
関数は1つの引数のみで実行されます。
単語分割の悪影響
$ a='I am a string with spaces'
$ [ $a = $a ] || echo "didn't match"
bash: [: too many arguments
didn't match
[ $a = $a ]
は[ I am a string with spaces = I am a string with spaces ]
[ $a = $a ]
と解釈されました。[
I am a string with spaces
あるtest
コマンドは、単一の引数ではなく、むしろそれは6つの引数です!
$ [ $a = something ] || echo "didn't match"
bash: [: too many arguments
didn't match
[ $a = something ]
は[ I am a string with spaces = something ]
解釈されました
$ [ $(grep . file) = 'something' ]
bash: [: too many arguments
grep
コマンドはスペースを含む複数行の文字列を返します。したがって、そこにいくつの引数があるのか想像できます:D
何のために、いつ、そしてなぜ基本的なのかを見てください。
単語分割の有用性
単語の分割が便利な場合があります:
配列を埋める:
arr=($(grep -o '[0-9]\+' file))
これは、 ファイル内のすべての数値で
arr
を埋めます
スペースで区切られた単語をループする:
words='foo bar baz'
for w in $words;do
echo "W: $w"
done
出力:
W: foo
W: bar
W: baz
空白を含まないスペースで区切られたパラメータを渡す:
packs='apache2 php php-mbstring php-mysql'
sudo apt-get install $packs
または
packs='
apache2
php
php-mbstring
php-mysql
'
sudo apt-get install $packs
これにより、パッケージがインストールされます。
$packs
を二重引用符で囲むとエラーになります。
Unquoetd
$packs
はapt-get
引数としてスペースで区切られたすべてのパッケージ名を送信しますが、引用すると$packs
文字列を単一の引数として送信し、apt-get
はapache2 php php-mbstring php-mysql
というパッケージをインストールしようとしますapache2 php php-mbstring php-mysql
明らかに存在しないapache2 php php-mbstring php-mysql
(最初のもの)
何のために、いつ、そしてなぜ基本的なのかを見てください。
セパレータの変更による分割
次の例のように、区切り記号をスペースから新しい行に簡単に置き換えることができます。
echo $sentence | tr " " "\n"
それは、可変sentence
値を分割し、それをそれぞれ1行ずつ表示します。