Можно ли изменить IFS локально в функции Bash? - PullRequest
0 голосов
/ 06 июня 2018

У меня есть функция, которая должна изменить IFS для своей логики:

my_func() {
  oldIFS=$IFS; IFS=.; var="$1"; arr=($var); IFS=$oldIFS
  # more logic here
}

Могу ли я объявить IFS как local IFS внутри функции, чтобы мне не нужно было беспокоиться о поддержке ее текущего значенияи восстановить позже?

Ответы [ 4 ]

0 голосов
/ 07 июня 2018

Я запутался, потому что я изменил значение IFS на : внутри функции (без использования local), а затем попытался отобразить значение IFS с помощью этой команды после вызова функции:

echo $IFS

, которая отображала пустую строку, из-за которой я чувствовал, что функция не меняет IFS.После публикации вопроса я понял, что разделение слов было в игре, и я должен был использовать

echo "$IFS"

или

printf '%s\n' "$IFS"

или, что еще лучше,

set | grep -w IFS=

для точного отображения значения IFS.

Возвращаясь к основной теме о локальных переменных, да, любая переменная может быть объявлена ​​как local внутри функции для ограничения области действия, за исключением переменных, которые были объявлены только для чтения.(с помощью встроенных команд readonly или declare -r).Это включает в себя Bash внутренние переменные, такие как BASH_VERSINFO и т. Д.

С help local:

local: local [option] name [= value] ...

Define local variables.

Create a local variable called NAME, and give it VALUE.  OPTION can
be any option accepted by `declare'.

Local variables can only be used within a function; they are visible
only to the function where they are defined and its children.

Exit Status:
Returns success unless an invalid option is supplied, a variable
assignment error occurs, or the shell is not executing a function.
0 голосов
/ 06 июня 2018

Похоже, что работает, как вы хотите.

#!/bin/bash
changeIFSlocal() {
    local IFS=.
    echo "During local: |$IFS|"
}
changeIFSglobal() {
    IFS=.
    echo "During global: |$IFS|"
}
echo "Before: |$IFS|"
changeIFSlocal
echo "After local: |$IFS|"
changeIFSglobal
echo "After global: |$IFS|"

Это печатает:

Before: |
|
During local: |.|
After local: |
|
During global: |.|
After global: |.|
0 голосов
/ 07 июня 2018

Вы можете обозначить IFS как local переменную;локальная версия по-прежнему используется в качестве строки-разделителя полей.

Иногда бывает полезно запустить функцию в полностью изолированной среде, где никакие изменения не являются постоянными.(Например, если функции необходимо изменить параметры оболочки.) Это может быть достигнуто путем запуска функции в подоболочке;просто измените {} в определении функции на ():

f() ( 
  shopt -s nullglob
  IFS=.
  # Commands to run in local environment
)
0 голосов
/ 06 июня 2018

Да, его можно определить!

Пока вы его определяете local, установка значения в функции не влияет на глобальное значение IFS.Смотрите разницу между фрагментами ниже

addNumbers () {
    local IFS='+'
    printf "%s\n" "$(( $* ))"
}

при вызове в командной строке как,

addNumbers 1 2 3 4 5 100
115

и выполнении

nos=(1 2 3 4 5 100)
echo "${nos[*]}"

из командной строки.hexdump в вышеприведенном выводе echo не будет показывать значение IFS, определенное в функции

echo "${nos[*]}" | hexdump -c
0000000   1       2       3       4       5       1   0   0  \n
000000e

Посмотрите в одном из моих ответов, как я использовал локализованный IFSсделать арифметику - Как добавить числа в скрипте bash

...