`while IFS = read..`でIFSが何も効果がないのはなぜですか?

`while IFS = read..`でIFSが何も効果がないのはなぜですか?

何かが間違っている可能性がありますが、IFSを次のいずれかに設定すると説得力があるようです。注文する事前完了/完了リストにはまったく影響しません。
外部IFS(while構成外)は、以下のスクリプトに示されているすべての例で支配的です。

ここで何が起こっているのでしょうか?この場合、IFSが何をしているのか私は間違った考えを持っていますか?配列分割の結果が「予想」列に示されているとおりであると予想しました。


#!/bin/bash
xifs() { echo -n "$(echo -n "$IFS" | xxd -p)"; } # allow for null $IFS 
show() { x=($1) 
         echo -ne "  (${#x[@]})\t |"
         for ((j=0;j<${#x[@]};j++)); do 
           echo -n "${x[j]}|"
         done
         echo -ne "\t"
         xifs "$IFS"; echo
}
data="a  b   c"
echo -e "-----   --  -- \t --------\tactual"
echo -e "outside        \t  IFS    \tinside" 
echo -e "loop           \t Field   \tloop" 
echo -e "IFS     NR  NF \t Split   \tIFS (actual)" 
echo -e "-----   --  -- \t --------\t-----"
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while         read; do echo -ne '\t 1'; show "$REPLY"; done 
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS=    read; do echo -ne '\t 2'; show "$REPLY"; done 
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS=b   read; do echo -ne '\t 3'; show "$REPLY"; done
IFS=" ";      xifs "$IFS"; echo "$data" | while         read; do echo -ne '\t 4'; show "$REPLY"; done 
IFS=" ";      xifs "$IFS"; echo "$data" | while IFS=    read; do echo -ne '\t 5'; show "$REPLY"; done 
IFS=" ";      xifs "$IFS"; echo "$data" | while IFS=b   read; do echo -ne '\t 6'; show "$REPLY"; done
IFS=;         xifs "$IFS"; echo "$data" | while         read; do echo -ne '\t 7'; show "$REPLY"; done 
IFS=;         xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne '\t 8'; show "$REPLY"; done 
IFS=;         xifs "$IFS"; echo "$data" | while IFS=b   read; do echo -ne '\t 9'; show "$REPLY"; done
IFS=b;        xifs "$IFS"; echo "$data" | while IFS=    read; do echo -ne '\t10'; show "$REPLY"; done
IFS=b;        xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne '\t11'; show "$REPLY"; done
echo -e "-----   --  -- \t --------\t-----"

出力:

-----   --  --   --------       actual   
outside           IFS           inside                assigned   
loop             Field          loop    #              inner
IFS     NR  NF   Split          IFS     #  expected    IFS
-----   --  --   --------       -----   #  ---------  --------
20090a   1  (3)  |a|b|c|        20090a  #                              
20090a   2  (3)  |a|b|c|        20090a  #  |a  b   c|  IFS=
20090a   3  (3)  |a|b|c|        20090a  #  |a  |   c|  IFS=b
20       4  (3)  |a|b|c|        20      #                          
20       5  (3)  |a|b|c|        20      #  |a  b   c   IFS=
20       6  (3)  |a|b|c|        20      #  |a  |   c|  IFS=b
         7  (1)  |a  b   c|             #                          
         8  (1)  |a  b   c|             #  |a|b|c|     IFS=" "
         9  (1)  |a  b   c|             #  |a  |   c|  IFS=b
62      10  (2)  |a  |   c|     62      #  |a  b   c|  IFS=
62      11  (2)  |a  |   c|     62      #  |a|b|c|     IFS=" "
-----   --  --   --------       -----      ---------   -------                        

ベストアンサー1

(説明が長くてすみません)

はい、IFSinの変数はwhile IFS=" " read; do …残りのコードには影響しません。

まず、シェルコマンドラインに2つの異なる種類の変数があることを指定します。

  • シェル変数(シェル内にのみ存在し、シェルのローカル変数です)
  • すべてのプロセスに環境変数が存在します。これは通常保存されるため、fork()exec()プロセスはそれを継承します。

以下を使用してコマンドを呼び出す場合:

  A=foo B=bar command

Afooコマンドは、(環境)変数がにB設定されている環境で実行されますbar。しかし、このコマンドラインを使用すると、現在のシェル変数AB絶え間ない

これは以下とは異なります。

A=foo; B=bar; command

Aシェル変数とはここで定義されており、Bコマンドは環境変数AB定義なしで実行されます。Aとの値Bはからアクセスできませんcommand

ただし、一部のシェル変数が-edの場合、exportその環境変数はそのシェル変数と同期されます。例:

export A
export B
A=foo; B=bar; command

このコードを使用すると、両方シェル変数とシェル環境変数fooはとに設定されますbar。環境変数は子プロセスに継承されるため、commandその値にアクセスできます。

元の質問に戻るには、次に進みます。

IFS='a' read

影響を受けるだけですread。実際、この場合、read変数の値は重要ではありませんIFSIFS行を分割して複数の変数に保存する必要がある場合にのみ使用してください。たとえば、次のようになります。

echo "a :  b :    c" | IFS=":" read i j k; \
    printf "i is '%s', j is '%s', k is '%s'" "$i" "$j" "$k"

IFSreadパラメーターを使用して呼び出さないと、使用されません。 (編集する:これは完全に正確ではありません。IFS入力行の先頭/末尾にある空白文字(スペースやタブなど)は常に無視されます。 )

おすすめ記事