Действительно ли возможно добавить функцию в функции?

В энергии просто нажимают * для поиска вперед... # будет искать назад.

О: предварительно ожидайте * и # с g, чтобы также распознать частичные слова.

6
28.02.2018, 20:40
4 ответа

Да, возможно.

Еще можно гнездиться функцией в другой функции, хотя это не очень полезно.

f1 ()
{

  f2 () # nested
  {
    echo "Function \"f2\", inside \"f1\"."
  }

}  

f2  #  Gives an error message.
    #  Even a preceding "declare -f f2" wouldn't help.

echo    

f1  #  Does nothing, since calling "f1" does not automatically call "f2".
f2  #  Now, it's all right to call "f2",
    #+ since its definition has been made visible by calling "f1".

    # Thanks, S.C.

Источник: Проект документации Linux

9
27.01.2020, 20:22

Вы можете определить функцию в любом месте оболочки ожидает команды, в том числе в функции. Обратите внимание, что в данный момент определена функция, которую оболочка выполняет его определение, а не когда оболочка анализирует файл. Таким образом, ваш код не будет работать, если пользователь выбирает вариант 1 в первый раз UPDATE_PROFILE , потому что, когда COMPLATE_NAME вызывается в операторе , определение функции update_name пока не будет выполнен. Как только функция update_profile выполнена один раз, также будет определена функция update_name .

Вам необходимо переместить определение UPDATE_NAME до того, как она используется.

Определение UPDATE_NAME Внутри update_profile не особенно полезно. Это означает, что UPDATE_NAME не будет определено до первого раз update_profile , но он останется доступен впоследствии. Если вы хотите UPDATE_NAME , чтобы быть доступным только внутри update_profile , определите функцию внутри него и вызовите Unset -f update_name Перед возвратом из функции. Вы действительно ничего не получите, делая это, хотя по сравнению с простым вещью и определением всех функций глобально.

3
27.01.2020, 20:22

Да, и это становится яснее, когда вы считаете, что действительно функция оболочки.

Для SOXIX-совместимых оболочек определение функции стандартизируется таким образом:

  • 2.9.5 Команда определения функции

    • Функция - это имя, которое используется в качестве Simple Command Чтобы вызвать составную команду с новыми позиционными параметрами . Функция определяется командой определения функции « » ... следующим образом:

    FNAME () Соединение-команда [IO-Redirect ...]

    • Функция называется fname ... Реализация должна поддерживать отдельные названные пространства для функций и переменных .

    • Аргумент Communic Command представляет собой составную команду , как описано в составных командах .

      • Когда объявлена ​​функция , ни один из разложений в расширений слов должен выполняться в тексте в Commual Command или << & IO-Redirect &> ; Все $ {Expansions} должны выполняться как обычные каждый раз, когда вызывается функция. Аналогично, необязательно << & IO-Redirect &> перенаправления и любые переменные = назначения в пределах соединения Comment должны выполняться во время выполнения самой функции, а не определение функции. См. Последствия ошибок оболочки Для последствий сбоев этих операций на интерактивных и неинтерактивных оболочках.

И вот в своем сердце функция оболочки имена fname , является буквальной строкой, состоящей из хотя бы одного COMBENT COMMENT , что оболочка вызовет из памяти и выполняется на месте Из Fname , когда это происходит в входе в командной позиции - что означает, где будет делать CMD . Это определение открывает много возможностей для использования функции в оболочке POSIX. Любое из следующего является приемлемым:

fn() {
    command; list;
    fn() { : redefines itself upon first execution; }
}

... и ...

fn() {
    helper1() { : defines another function which it can call; }
    helper2() { : and another; }
    helper1 "$@" | helper2 "$@"     #processes args twice over pipe
    command "$@"; list;             #without altering its args
}

Но это небольшой пример. Если вы рассматриваете значение Communic Command , вы можете начать видеть, что обычное Fn () {: CMDS; } Форма только в одну сторону функция может работать. Рассмотрим некоторые различные виды составных команд:

 { compound; list; of; commands;} <>i/o <i >o
 (subshelled; compound; list; of; commands) <>i/o <i >o
 if ...; then ...; fi <>i/o <i >o
 case ... in (...) ...;; esac <>i/o <i >o
 for ... [in ... ;] do ...; done <>i/o <i >o
 (while|until) ...; do ....; done <>i/o <i >o

и другие, кроме. Любой из вышеперечисленных должен работать как ...

 fname() compound list

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

Вот один из способов написать вашу функцию:

update_prof(){
    cat >&3
    read "${2-option}" <&3
    case "${1-$option}" in
    1) update_prof '' name      ;;
    2) update_prof '' age       ;;
    3) update_prof '' gender    ;;
    *) unset option             ;;
    esac
} <<-PROMPT 3<>/dev/tty
${1-
    1. Update Name
    2. Update Age
    3. Update Gender
}
    Enter ${2:-option}: $(
        printf '\033%s' \[A @
)
PROMPT

Некоторые заметки о вышеупомянутых:

  1. Чтение в обновлении подлежит интерпретации IFS и интерпретации обратной кости. Оценительно это может быть IFS = Read -R «$ 1» , но я не уверен, как вы хотите, чтобы эти вещи были интерпретированы. Ищите другие ответы на этом сайте для более и лучшей информации по этому результату.
  2. Printf '\ 033% S ... в здесь предполагается / dev / tty связано с совместимым клемма VT100, в этом случае используемое место Сохраняйте окончательную новую строку здесь доктора от отображения на экране. Устойчивая TUTP будет использоваться. Сделайте MAN TERMCAP для получения дополнительной информации.
    • Лучшее - это предположение VT100 является правильным, и вы можете сделать без PrintF , либо TPUTPUT , введя символы Escape буквально в документ здесь ^ v {esc } [A ^ V {Esc} @ Где ^ v - способ представления комбинации клавиш + V и {ESC} Клавиша клавиатуры esc .

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

Итак, если я бегу ...

update_prof; printf %s\\n "$name"

Внужденная терминальная активность выглядит как:

1. Update Name
2. Update Age
3. Update Gender

Enter option: 1

Enter name: yo mama
yo mama
2
27.01.2020, 20:22

Я повторно -добавляю сюда свой ответ, который Джефф Шаллер удалил, чтобы убедиться, что есть ответ, который показывает, что действительно существует вариант использования, и по своей сути неправильно говорить «это не очень полезно», на что намекает принятый ответ.

Вот еще раз (исправлено, чтобы показать, что я имею в виду под ответом):

Это "не очень полезно"? Я думаю, что это на самом деле довольно круто.

У меня есть специальные функции инициализации проекта -в моих bashrc/ bash_aliases, которые инициализируют мою среду для данного проекта.

До этого у меня были глобально определены все псевдонимы и функции (ярлыки, такие как cdprojectnameи modulename_buildи подобные ). Проблема в том, что вы можете легко использовать очень длинные имена, чтобы избежать конфликтов имен после работы над большим количеством проектов.

Итак, что я сделал, так это то, что я взялcdprojectname(вроде cdsdдля проекта sd), и это функция, которая не только переходит в каталог проекта, но и инициализирует всю мою среду разработки, когда дело доходит до проекта..

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

.
  • ага я проверил и там с моими фокусами не работает
  • jaja, что бы это ни было, это даже не работает, если я запускаю cdsdиз vim сейчас -все еще крутая функция, как она есть!

Что касается комментариев к ответу

"Please don't add "thank you" as an answer. Once you have sufficient reputation, you will be able to vote up questions and answers that you found helpful. – Jeff Schaller"

Извините, у меня нет возможности написать вам, но я не написал то, что написал в качестве благодарности, но я видел из более ранних комментариев/ответов, которые не особо освещают возможный вариант использования для этого, некоторые даже говорят " Можно даже вложить функцию в другую функцию, хотя это не очень полезно "

Это не благодарность, но хочу отметить, что вместо «это не очень полезно» это на самом деле «действительно -действительно полезная и удобная функция», которая была бы полезна для других языков сценариев/оболочек. есть на самом деле!

Я опубликовал свой ответ, потому что категорически не согласен с тем, что это не очень полезно, но принятый в настоящее время ответ намекает на это... пожалуйста, отредактируйте так, как хотите, или просто сохраните его, иначе в принятом ответе есть ложная информация/подсказка I думать.

0
23.04.2020, 12:12

Теги

Похожие вопросы