Как защитить функцию bash от переопределения? Сделать это доступным только для чтения

Точка с запятой между условными блоками не обязательна; только точки с запятой между операторами внутри блоков кажутся обязательными:

$ echo -e "foo\nbar" | gawk '/foo/ { print "foo found" } /bar/ {print "bar found"}'
foo found
bar found
$ echo -e "foo\nbar" | gawk '/foo/ { print "foo found" }; /bar/ {print "bar found"}'
foo found
bar found
$ echo -e "foo\nbar" | gawk '/foo/ { print "foo found"; print "whee" }'
foo found
whee
$ echo -e "foo\nbar" | gawk '/foo/ { print "foo found" print "whee" }'
gawk: cmd. line:1: /foo/ { print "foo found" print "whee" }
gawk: cmd. line:1:                           ^ syntax error

Однако, когда фактический блок кода между двумя условными операторами опущен в пользу стандартного (i. е. {print}),точка с запятой становится необходимой:

$ echo -e "foo\nbar" | gawk '/foo/ /bar/'
gawk: cmd. line:2: /foo/ /bar/
gawk: cmd. line:2:            ^ unexpected newline or end of string
$ echo -e "foo\nbar" | gawk '/foo/; /bar/'
foo
bar
12
27.09.2019, 12:52
2 ответа

Вы можете объявить функцию fooкак функцию -только для чтения, используя readonly -f fooилиdeclare -g -r -f foo(readonlyэквивалентноdeclare -g -r). Опция -fдля этих встроенных -утилит заставляет их работать с fooкак с именем функции, а не с переменной foo.

$ foo () { echo Hello; }
$ readonly -f foo
$ foo () { echo Bye; }
bash: foo: readonly function
$ unset -f foo
bash: unset: foo: cannot unset: readonly function
$ foo
Hello

Как видите, чтение функции -не только защищает ее от переопределения, но и защищает от полной отмены (удаления ).


В настоящее время (по состоянию наbash-5.0.11)попытка модифицировать функцию -только для чтения не приведет к завершению работы оболочки, если используется опция оболочки errexit(set -e). Чет, сопровождающий bash, говорит, что это недоработка и что она будет исправлена ​​в следующем выпуске.

Обновление :Это было исправлено в октябре 2019 года для bash-5.1-alpha, поэтому любая bashверсия 5.1 или более поздняя завершалась корректно, если попытка изменить функцию -только для чтения была предпринята во время работы оболочки errexit. опция активна.

31
27.01.2020, 19:54

Небольшое замечание к ответу @Kusalananda. Согласно тому, что сопровождающий bash сказал, что изменение функции только для чтения -вызовет завершение работы оболочки при использовании set -e.

Я использую Ubuntu 20.10 с более новой версией bash. К сожалению, похоже, он сломан.

$ bash --version
GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)

test.sh

#!/usr/bin/env bash

set -e

test() {
    echo "I'm test() function"
}
readonly -f test

test

test() { # should exit here
    echo "I'm test() function (duplicated)"
}
test

Выход

$ chmod +x test.sh;./test.sh
I'm test() function
./test.sh: line 14: test: readonly function
I'm test() function

Я протестировал этот скрипт внутри контейнера докеров, используя последнюю версию bash, и он работает должным образом.

GNU bash, version 5.1.8(1)-release (x86_64-pc-linux-musl)
0
17.05.2021, 09:33

Теги

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