内部フィールド区切り記号(IFS)を複数の連続区切り記号の単一区切り文字として使用できますか?

内部フィールド区切り記号(IFS)を複数の連続区切り記号の単一区切り文字として使用できますか?

空白以外の値でIFSを使用して配列を解析すると、空の要素が生成されます。複数の区切り文字を単一の区切り記号に縮小する
だけでは十分ではありません。たとえば、問題をより明確に説明できます。 IFSを調整して「正常な」結果を得る方法はありますか(IFSの動作を変更する関連設定はありますか?....つまり、デフォルトの空白IFSと同じ動作です)。tr -s

var=" abc  def   ghi    "
echo "============== IFS=<default>"
arr=($var)
for x in ${!arr[*]} ; do
   echo "# arr[$x] \"${arr[x]}\""
done
#
sfi="$IFS" ; IFS=':'
set -f # Disable file name generation (globbing)
       # (This  data won't "glob", but unless globbing     
       #  is actually needed, turn if off, because   
       #  unusual/unexpected combinations of data can glob!
       #  and they can do it in the most obscure ways...  
       #  With IFS, "you're not in Kansas any more! :)  
var=":abc::def:::ghi::::"
echo "============== IFS=$IFS"
arr=($var)
for x in ${!arr[*]} ; do
   echo "# arr[$x] \"${arr[x]}\""
done
echo "============== IFS=$IFS and tr"
arr=($(echo -n "$var"|tr -s "$IFS"))
for x in ${!arr[*]} ; do
   echo "# arr[$x] \"${arr[x]}\""
done
set +f     # enable globbing 
IFS="$sfi" # re-instate original IFS val
echo "============== IFS=<default>"

これが出力です


============== IFS=<default>
# arr[0] "abc"
# arr[1] "def"
# arr[2] "ghi"
============== IFS=:
# arr[0] ""
# arr[1] "abc"
# arr[2] ""
# arr[3] "def"
# arr[4] ""
# arr[5] ""
# arr[6] "ghi"
# arr[7] ""
# arr[8] ""
# arr[9] ""
============== IFS=: and tr
# arr[0] ""
# arr[1] "abc"
# arr[2] "def"
# arr[3] "ghi"
============== IFS=<default>

ベストアンサー1

bashマンページから:

IFS スペースではなく、IFS のすべての文字と隣接する IFS スペース文字が一緒にフィールドを区別します。空白文字の IFS シーケンスも区切り文字と見なされます。

示すIFS スペース(スペース、タブ、改行)は、他の区切り文字とは異なる方法で処理されます。代替区切り記号を使用してまったく同じ動作を得るには、またはtr次のように区切り文字を置き換えることができますsed

var=":abc::def:::ghi::::"
arr=($(echo -n $var | sed 's/ /%#%#%#%#%/g;s/:/ /g'))
for x in ${!arr[*]} ; do
   el=$(echo -n $arr | sed 's/%#%#%#%#%/ /g')
   echo "# arr[$x] \"$el\""
done

これは%#%#%#%#%、「固有」(または非常に関連性がないこと)フィールド内の可能な空白を置き換える魔法の値です。フィールドにスペースがないと確信している場合は、この部分を削除してください。

おすすめ記事