Внутри Vi (или Vim):
:%s#^05/08/2017#04/03/2017#
Возможно, вам придется сначала нажать Esc , чтобы выйти из режима вставки.
Как и в sed
, вы можете выбрать произвольный символ в качестве разделителя шаблона при подстановке с помощью команды s
. Здесь я выбрал #
.
Шаблон ^05/08/2017
будет соответствовать началу строки из-за ^
. Это предотвращает случайное совпадение в другом месте любой строки.
С обычным /
в качестве разделителя шаблона мы получаем хороший пример того, что называется «синдромом наклонной зубочистки »:
:%s/^05\/08\/2017/04\/03\/2017/
Команда подстановки будет выполняться для всех строк в текущем буфере Vi, так как мы используем %
в начале для «диапазона»(%
идентично 1,$
, т.е. «от первой строки до последней». последняя строка» ).
Обратите внимание, что ksh88 и все его клоны выполняют динамическую область видимости и поддерживают local
для него, по крайней мере, с 1990 г. для ksh88 и 1994 г. дляpdksh
(и 1989 г. для bash
, который (теперь )реализует многое. API ksh88 ).
ksh
, о котором вы говорите, — это ksh93
, более новая реализация с нуля, разработанная Дэвидом Корном с немного другим и несовместимым API.
Это хорошая идея называть эту оболочку как ksh93
, а не просто ksh
, поскольку ksh
само по себе означало ksh88
API в течение нескольких десятилетий (, который реализуют все, кроме реализации ksh93 ). ksh93
не использовался широко до нескольких лет после 2000 года, когда его код был выпущен как открытый исходный код.
ksh93 typeset
выполняет только статическую область видимости. POSIX возражал против указания ksh88 typeset
/ local
на том основании, что это была динамическая область видимости (, хотя большинство языков, таких как C, делают статическую область видимости, динамическую область видимости. происходит более естественно в оболочках, поскольку это то, что вы получаете с помощью подоболочек или среды ), что объясняет, почему ksh93 был переписан для статического копирования.
Позднее в большинстве других оболочек была реализована область видимости а-ля ksh88, так что ksh93 теперь лишний. И теперь, по иронии судьбы, единственным разумным вариантом POSIX было бы указать динамическую область. В то время как Дэвид Корн изначально отказался реализовать динамическую область видимости в ksh93,он сказал, что может рассмотреть это с ключевым словом/встроенной командой local
в списке рассылки POSIX, но он ушел в отставку до того, как это полностью произошло.
Бета-версия ksh93v -и окончательная версия от AT&T могут быть скомпилированы с экспериментальным режимом «bash» (, фактически включенным по умолчанию ), который выполняет динамическую область видимости (в любых формах функций, в том числе с local
и typeset
), когда ksh93
вызывается как bash
. Этот режим bash
будет отключен по умолчанию в ksh2020 , хотя псевдонимы local
/ declare
для typeset
будут сохранены, даже если режим bash не скомпилирован в(хотя все еще со статической областью видимости ).
Теперь, если мы оставим эту бета-версию в стороне и ее режим bash, ksh93 только выполняет статическую область видимости и только в функциях, объявленных с синтаксисом стиля ksh -(function name { code; }
). Вы запутались, потому что функции, объявленные с синтаксисом стиля Bourne -(f() command
), вообще не выполняют область видимости . То же самое с исходными файлами или функциями ksh, вызываемыми с помощью . name [args]
. В них typeset
не объявляется новая переменная в области действия функции (, эта функция не имеет области действия ), она просто обновляет тип переменной в текущей области, которая будет либо глобальной областью или область действия функции стиля ksh -, если этот стиль Bourne -был (в конечном итоге )вызван из функции стиля ksh -.
Код функций в стиле Bourne -запускается так, как будто встроенные/скопированные -вставленные/исходные, где бы они ни вызывались.
var=global
function ksh_function {
typeset var=private
echo "ksh1: $var"
bourne_function
echo "ksh2: $var"
other_ksh_function other
echo "ksh3: $var"
. other_ksh_function other_invoked_with_dot
echo "ksh4: $var"
}
bourne_function() {
typeset var=set-from-bourne-function
}
function other_ksh_function {
echo "other: $var"
var=$1
}
ksh_function
echo "global: $var"
Дает:
ksh1: private
ksh2: set-from-bourne-function
other: global
ksh3: set-from-bourne-function
other: set-from-bourne-function
ksh4: other_invoked_with_dot
global: other
В ksh93 невозможно иметь динамическую область видимости, кроме как с помощью подоболочек или самостоятельной реализации стека переменных, как в этом locvar
доказательстве концепции или вы экспортируете переменную чтобы он передавался каждой команде (, включая функции, объявленные с помощью функций стиля ksh -,включая внешние команды через среду ).
В вашем конкретном случае, когда только функция testlocal
(, а неtestdescend
)нуждается в локальной области, вы можете использовать подход shdef
+ kshdef
, как описано там или сделать что-то вроде:
case $KSH_VERSION in
(*" 93"*)
fn_with_local_scope() {
alias local=typeset
eval "function $1 {
$(cat)
}"
}
;;
(*)
fn_with_local_scope() {
eval "$1() {
$(cat)
}"
}
;;
esac
А затем объявите свои функции как:
fn_with_local_scope testlocal << '}'
local IFS
IFS=123
echo "internal IFS = $IFS"
testdescend
}
testdescend(){
echo "descended IFS = $IFS"
}
IFS=abc
testlocal
echo "external IFS = $IFS"
(и используйте local
только в функциях, объявленных с помощьюfn_with_local_scope
).
Что дает
internal IFS = 123
descended IFS = 123
external IFS = abc
во всех оболочках (обратите внимание, что вам нужна последняя версияyash
(2.48 или выше )для поддержкиlocal
).
Или, если вы согласны, чтобы локальные переменные также экспортировались (только в ksh93):
case $KSH_VERSION in
(*" 93"*)
fn() {
alias local='typeset -x'
eval "function $1 {
$(cat)
}"
}
;;
(*)
fn() {
eval "$1() {
$(cat)
}"
}
;;
esac
fn testlocal << '}'
local IFS
IFS=123
echo "internal IFS = $IFS"
testdescend
}
fn testdescend << '}'
echo "descended IFS = $IFS"
}
IFS=abc
testlocal
echo "external IFS = $IFS"
Теперь, если бы вы сделали что-то подобное на языке со статической областью видимости, такой как C или ksh93, вы бы сделали что-то вроде:
function testlocal {
typeset IFS
IFS=123
echo "internal IFS = $IFS"
testdescend "$IFS"
}
function testdescend {
typeset IFS="$1" # explicitly get the value $IFS from the caller
echo "descended IFS = $IFS"
}
Мне кажется, что это лучший дизайн, и этот код также будет нормально работать в оболочках с динамической областью видимости (вам все равно нужно будет обратиться к другому синтаксису определения функции ).
Дополнительная литература:
Нет local
используется(отсутствует вообще ).
Я нашел не полностью работающее решение, а частичное, которое работает на dash, bash и zsh (по крайней мере ). Просто вызовите функцию с набором переменных окружения:
IFS=123 testlocal
Вы можете протестировать на(Попробуйте онлайн!).
Оболочка ksh (yes ksh93 на используемом сервере )немного сложнее, так как имеет двойную личность. Но обе личности представлены по ссылке выше.
Я предпочитаю bash (лучший синтаксис массива IMO ), но иногда сталкиваюсь с ksh-скриптами, поэтому я стараюсь использовать их, когда это удобно:
Всегда используйте синтаксис function func_name { body; }
.
Исходя из вышеизложенного, чтобы использовать local
ключевое слово :перед первой функцией, используйте:
# teach ksh 93 about local
case "$KSH_VERSION" in *' 93'*) alias local='typeset -x' ;; esac
Чтобы получить имя функции внутри функции :, используйте:
local MYNAME="${FUNCNAME[0]:-$0}"