一行単位でデータを扱いたいが、シェルの区切り文字がスペースになっていて変更できないかなぁ?と思っている方は、本記事が役に立つと思います。
尚、使用したシェルはbashになります。
以下のようなデータファイルがあり、スペース区切りで1行に3つの項目が格納されているファイルを利用して説明します。
$ cat data.txt Fedora Debian Ubuntu Vine Plamo CentOS openSUSE KNOPPIX Slackware
シェルの区切り文字を変更しないと以下のように、項目毎表示されてしまいます。
#!/bin/bash i=0 for L in `cat data.txt` do i=`expr $i + 1` echo $i : $L done
$ ./test.sh 1 : Fedora 2 : Debian 3 : Ubuntu 4 : Vine 5 : Plamo 6 : CentOS 7 : openSUSE 8 : KNOPPIX 9 : Slackware
本当は3行として出力を期待しているのだが、区切り文字がスペース(改行含む)のため、9項目として処理されてしまう。
IFS(Internal Field Separator )に区切り文字を設定することにより解決できます。
以下にサンプルスクリプトを記します。
#!/bin/bash IFS_BACKUP=$IFS IFS=$'\n' i=0 for L in `cat data.txt` do i=`expr $i + 1` echo $i : $L done IFS=$IFS_BACKUP
上記のIFS_BACKUPに変更前の区切り文字設定をバックアップしIFS環境変数を改行のみ指定します。
処理終了後、IFS_BACKUP変数を使用しIFS環境変数の設定を元に戻しています。
$ ./test2.sh 1 : Fedora Debian Ubuntu 2 : Vine Plamo CentOS 3 : openSUSE KNOPPIX Slackware
以下の2つは同じ意味になります。
IFS=$'\n'
IFS =' '
上記は直接改行を入力した状態です。
#!/bin/bash IFS_BACKUP=$IFS IFS=' ' i=0 for L in `cat data.txt` do i=`expr $i + 1` echo $i : $L done IFS=$IFS_BACKUP
以下のテストデータを利用し改行の他に他の区切り文字も設定してみます。
$ cat data2.txt Fedora,Debian,Ubuntu Vine#Plamo#CentOS openSUSE&KNOPPIX&Slackware
区切り文字を、改行、#、, 、&の4つとした場合は以下のIFS設定になります。
#!/bin/bash IFS_BACKUP=$IFS IFS=' ,&#' i=0 for L in `cat data2.txt` do i=`expr $i + 1` echo $i : $L done IFS=$IFS_BACKUP
$ ./test4.sh 1 : Fedora 2 : Debian 3 : Ubuntu 4 : Vine 5 : Plamo 6 : CentOS 7 : openSUSE 8 : KNOPPIX 9 : Slackware
1行に複数の項目がある場合、IFSの変更により区切り文字を変更することができるため、データの扱いが便利になります。
1行として扱いたいと思う事が多いと思います。
上記のサンプルによりIFSを改行だけと設定すれば簡単にデータを取り扱う事ができます。
また、区切り文字を複数にする方法も記述しました。
最後にIFSのバックアップは必ず取るようにし、区切り文字の変更が必要な場所のみで使用し、その後、バックアップからIFSを元にもどしましょう。
そうしないと、意図しない動作になるかもしれませんので。