サーチ…
構文
- 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つの引数に分割されます。Iam\na\nmultilineとstringが印刷されます
IFSを改行のみに設定しましょう:
IFS=$'\n'
...
今度のfunは次のように実行されます:
fun 'I am' a 'multiline string'
$varは3つの引数に分割されます。I am、 、amultiline 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行ずつ表示します。