bash:読み取りコマンドはIFSをサポートしません。

bash:読み取りコマンドはIFSをサポートしません。

このコマンドのbashのマニュアルページからread

標準入力または-uオプションの引数として指定されたファイル記述子fdから1行を読み取り、上記の単語の分割で説明されているように単語に分割し、最初の単語を名前に割り当てます。

今、私は次を試しました。

IFS=,
echo ' a b,c d'|read -n 4 x y
echo ".$x. .$y."

私の予想結果は

. a b. .c d.

変更のため、トークン化はスペースの代わりにコンマでなければなりませんが、実際の出力は次のようになります。

.a. ..

これは私を混乱させる。スペースでは、単語の区切りはまだ実行されているように見えますが、少なくともスペースでは.a.ないyに設定する必要がありますb

read私はマニュアルページでこのコマンドの説明を間違って理解しているような気がしません。

ところで、私はbash 4.4.12を使用しています。

ベストアンサー1

うまく動作します:

$ IFS=,; echo ' a b,c d' | { read x y; declare -p x y;}
declare -- x=" a b"
declare -- y="c d"

ノート

  1. ステートメントはパイプにあるため、readステートメントはサブシェルにあります。変数xsum の範囲はyこのサブシェルに制限されます。上記では、declareステートメントが同じサブシェルにあるように中括弧を追加しましたread。これにより、文の出力に読み取られたx値とy値が表示されます。

    中かっこを削除すると、declare文は同じサブシェルになくなり、x値はy保持されません。観察する:

    $ x=hot; y=cold; IFS=,; echo ' a b,c d' | read -n 4 x y; declare -p x y
    declare -- x="hot"
    declare -- y="cold"
    
  2. サブシェルの制限を避けるためにhere-stringを使用できます。

    $ IFS=,; read x y <<<' a b,c d'; declare -p x y
    declare -- x=" a b"
    declare -- y="c d"
    

    here-string を使用すると、ステートメントはデフォルトのシェルにあり、read値は失われません。xy

  3. -n 4制限readは4文字です。これはあなたが望むものではないかもしれません。観察する:

    $ IFS=,; echo ' a b,c d' | { read -n 4 x y; declare -p x y;}
    declare -- x=" a b"
    declare -- y=""
    

    ここでは、 x4つの文字がすべて使用され(スペースは文字と見なされます)、文字は読み取られませんy

  4. 〜のようにペサまたはコマンドを実行するためにローカルにシェル変数を割り当てることもできます。 IFSを変更すると、後続のコマンドで不要な副作用が発生する可能性があるため、これは良い考えです。したがって:

    $ IFS=, read x y <<<' a b,c d'; declare -p x y
    declare -- x=" a b"
    declare -- y="c d"
    

    上記のコマンドが実行されると、IFS前の値に戻ります。

おすすめ記事