Эти команды вставят вывод strftime("%c")
право, где Ваш курсор:
:exe ":normal i" . strftime("%c")
и
:call feedkeys("i". strftime("%c"))
Существуют другие способы сделать то, что Вы хотите (как, например, те, которые на ответе Mikel).
Править: Еще лучше, для оперативной вставки, используйте =
зарегистрируйтесь, как Chris Johnsen описывает
Для нормализации наклонных черт во всех параметрах я буду использовать вращающийся прием аргумента: сдвиг $1
прочь, преобразуйте его и поместите результат в конце списка параметров. Если Вы делаете это столько же время, сколько существуют параметры, Вы преобразовали все параметры, и у Вас есть они назад в порядке.
Для второй части кода я изменил Вашу логику, чтобы менее сбивать с толку: внешний цикл выполняет итерации по параметрам, и внутренний цикл выполняет итерации по компонентам контура. for x; do … done
выполняет итерации по позиционным параметрам, это - удобная идиома. Я использую совместимый POSIX способ соответствовать строке против шаблона: case
создать.
Протестированный с тире 0.5.5.1, pdksh 5.2.14, удар 3.2.39, удар 4.1.5, ksh 93 +, zsh 4.3.10.
Примечание стороны: кажется, существует ошибка в ударе 4.1.5 (не в 3,2): если шаблон случая "${common_path%/}"/*
, один из тестовых сбоев.
posix_path_common () {
for tmp; do
tmp=$(printf %s. "$1" | tr -s "/")
set -- "$@" "${tmp%.}"
shift
done
common_path=$1; shift
for tmp; do
while case ${tmp%/}/ in "${common_path%/}/"*) false;; esac; do
new_common_path=${common_path%/*}
if [ "$new_common_path" = "$common_path" ]; then return 1; fi
common_path=$new_common_path
done
done
printf %s "$common_path"
}
Если Вы находитесь в ударе (или ksh), можно использовать массивы — я не понимаю, почему Вы, кажется, ограничиваете себя позиционными параметрами. Вот версия, которая использует массив. Я должен признать, что это не особенно более ясно, чем версия POSIX, но это действительно избегает начальной буквы n^2 перестановка.
Для части нормализации наклонной черты я использую конструкцию ksh93 ${foo//PATTERN/REPLACEMENT}
создайте для замены всех случаев PATTERN
в $foo
REPLACEMENT
. Шаблон +(\/)
для соответствия одному или нескольким режут; под ударом, shopt -s extglob
должен быть в действительности (эквивалентно, запустите удар с bash -O extglob
). Конструкция set ${!a[@]}
устанавливает позиционные параметры на список нижних индексов массива a
. Это обеспечивает удобный способ выполнить итерации по элементам массива.
Для второй части, я та же логика цикла как версия POSIX. На этот раз я могу использовать [[ … ]]
так как все оболочки, предназначенные здесь, поддерживают его.
Протестированный с ударом 3.2.39, колотите 4.1.5, ksh 93 +.
array_path_common () {
typeset a i tmp common_path new_common_path
a=("$@")
set ${!a[@]}
for i; do
a[$i]=${a[$i]//+(\/)//}
done
common_path=${a[$1]}; shift
for tmp; do
tmp=${a[$tmp]}
while [[ "${tmp%/}/" != "${common_path%/}/"* ]]; do
new_common_path="${common_path%/*}"
if [[ $new_common_path = $common_path ]]; then return 1; fi
common_path="$new_common_path"
done
done
printf %s "$common_path"
}
К сожалению, zsh недостает ${!array[@]}
функция для выполнения ksh93 версии как есть. К счастью, zsh имеет две функции, которые делают первую часть бризом. Можно индексировать позиционные параметры, как будто они были @
массив, таким образом, нет никакой потребности использовать промежуточный массив. И zsh имеет итеративную конструкцию массива: "${(@)array//PATTERN/REPLACEMENT}"
выполняет замену шаблона на каждом элементе массива в свою очередь и оценивает к массиву результатов (смутно, Вам действительно нужны двойные кавычки даже при том, что результатом являются несколько слов; это - обобщение "$@"
). Вторая часть чрезвычайно неизменна.
zsh_path_common () {
setopt local_options extended_glob
local tmp common_path new_common_path
set -- "${(@)@//\/##//}"
common_path=$1; shift
for tmp; do
while [[ "${tmp%/}/" != "${common_path%/}/"* ]]; do
new_common_path="${common_path%/*}"
if [[ $new_common_path = $common_path ]]; then return 1; fi
common_path="$new_common_path"
done
done
printf %s "$common_path"
}
Мои решения минимально тестируются и комментируются. Я изменил синтаксис Ваших тестовых сценариев для парсинга под оболочками, которые не имеют $'…'
и отказы отчета более удобным способом.
do_test () {
if test "$@"; then echo 0; else echo $? "$@"; failed=$(($failed+1)); fi
}
run_tests () {
function_to_test=$1; shift
failed=0
do_test "$($function_to_test /a/b/c/d /a/b/e/f; echo x)" = /a/bx
do_test "$($function_to_test /long/names/foo /long/names/bar; echo x)" = /long/namesx
do_test "$($function_to_test / /a/b/c; echo x)" = /x
do_test "$($function_to_test a/b/c/d a/b/e/f ; echo x)" = a/bx
do_test "$($function_to_test ./a/b/c/d ./a/b/e/f; echo x)" = ./a/bx
do_test "$($function_to_test '
/
/
' '
/
'; echo x)" = '
/
'x
do_test "$($function_to_test --/-- --; echo x)" = '--x'
do_test "$($function_to_test '' ''; echo x)" = x
do_test "$($function_to_test /foo/bar ''; echo x)" = x
do_test "$($function_to_test /foo /fo; echo x)" = x
do_test "$($function_to_test '--$`\! *@ \a\b\e\E\f\r\t\v\\\"'\''
' '--$`\! *@ \a\b\e\E\f\r\t\v\\\"'\''
'; echo x)" = '--$`\! *@ \a\b\e\E\f\r\t\v\\\"'\''
'x
do_test "$($function_to_test /foo/bar //foo//bar//baz; echo x)" = /foo/barx
do_test "$($function_to_test foo foo; echo x)" = foox
do_test "$($function_to_test /fo /foo; echo x)" = x
if [ $failed -ne 0 ]; then echo $failed failures; return 1; fi
}
Почему Вы только не используете 1$, 2$.. 9$, $ {10}, $ {11}.. и так далее? Это - еще больше СУШИЛКИ, чем, что Вы пытаетесь сделать :)
Больше на отношении между $number и $:
$ можно рассмотреть как сокращение от "всех элементов массива, содержащего все аргументы"
Так, $ является своего рода стенографией $ {args} (args, вот 'виртуальный' массив, содержащий все аргументы - не реальная переменная, обратите внимание),
1$ является $ {args [1]}, 2$ $ {args [2]}, и так далее.
Когда Вы совершите нападки [9], используйте фигурную скобку: $ {10} является $ {args [10]}, $ {11} является $ {args [11]} и так далее.
argnum=3 # You want to get the 3rd arg
do-something ${!argnum} # Do something with the 3rd arg
Пример:
argc=$#
for (( argn=1; argn<=argc; argn++)); do
if [[ ${!argn} == "foo" ]]; then
echo "Argument $argn of $argc is 'foo'"
fi
done
${args[$i]}
.
– intuited
16.04.2011, 08:08
Первый аргумент используется, с одной стороны, и остальные для чего-то еще,
Я думаю, что Вы хотите, shift
$ set one two three four five
$ echo $@
one two three four five
$ echo $1
one
$ foo=$1
$ echo $foo
one
$ shift
$ echo $@
two three four five
$ shift 2
$ echo $@
four five
$ echo $1
four
Я не вполне знаю, почему Вы только не используете $1$ 2 и т.д. но.. Это может удовлетворить Вашим потребностям.
$ script "ed it" "cat/dog" 33.2 \D
echo "-------- Either use 'indirect reference'"
for ((i=1;i<=${#@};i++)) ;do
# eval echo \"\$$i\" ..works, but as *pepoluan*
# has pointed out: echo "${!i}" ..is better.
echo "${!i}"
done
echo "-------- OR use an array"
array=("$@")
for ((i=0;i<${#array[@]};i++)) ;do
echo "${array[$i]}"
done
echo "-------- OR use 'set'"
set "$@"
echo "$1"
echo "$2"
echo "$3"
echo "$4"
вывод
-------- Either use 'indirect reference'
ed it
cat/dog
33.2
D
-------- OR use an array
ed it
cat/dog
33.2
D
-------- OR use 'set'
ed it
cat/dog
33.2
D
set
работы чего-либо, что следует за ним, для создания 1$, 2$ и т.д. Это, конечно, переопределит исходные значения, поэтому просто знать об этом.
eval
как полагают, некоторыми, evil
... (возможно, это из-за написания :)... Если eval
"плохо", затем $ {! var} одинаково "плохо"?... Мне это - просто часть языка и полезная часть, в этом.. но я определенно предпочитаю $ {! var}...
– Peter.O
27.04.2011, 05:03
Обратите внимание, что я поддерживаю пробелы в именах файлов.
function SplitFilePath {
IFS=$'/' eval "${1}"=\( \${2} \)
}
function JoinFilePath {
IFS=$'/' eval echo -n \"\${*}\"
[ $# -eq 1 -a "${1}" = "" ] && echo -n "/"
}
function path_common {
set -- "${@//\/\///}" ## Replace all '//' with '/'
local -a Path1
local -i Cnt=0
SplitFilePath Path1 "${1}"
IFS=$'/' eval set -- \${2}
for CName in "${Path1[@]}" ; do
[ "${CName}" != "${1}" ] && break;
shift && (( Cnt++ ))
done
JoinFilePath "${Path1[@]:0:${Cnt}}"
}
Я добавил тестовый сценарий для имен файлов с пробелами и зафиксировал 2 теста, которые пропускали продвижение /
do_test () {
if test "${@}"; then echo 0; else echo $? "$@"; failed=$(($failed+1)); fi
}
run_tests () {
function_to_test=$1; shift
failed=0
do_test "$($function_to_test /a/b/c/d /a/b/e/f; echo x)" = /a/bx
do_test "$($function_to_test /long/names/foo /long/names/bar; echo x)" = /long/namesx
do_test "$($function_to_test / /a/b/c; echo x)" = /x
do_test "$($function_to_test a/b/c/d a/b/e/f ; echo x)" = a/bx
do_test "$($function_to_test ./a/b/c/d ./a/b/e/f; echo x)" = ./a/bx
do_test "$($function_to_test '
/
/
' '
/
'; echo x)" = '
/
'x
do_test "$($function_to_test --/-- --; echo x)" = '--x'
do_test "$($function_to_test '' ''; echo x)" = x
do_test "$($function_to_test /foo/bar ''; echo x)" = x
do_test "$($function_to_test /foo /fo; echo x)" = /x ## Changed from x
do_test "$($function_to_test '--$`\! *@ \a\b\e\E\f\r\t\v\\\"'\''
' '--$`\! *@ \a\b\e\E\f\r\t\v\\\"'\''
'; echo x)" = '--$`\! *@ \a\b\e\E\f\r\t\v\\\"'\''
'x
do_test "$($function_to_test /foo/bar //foo//bar//baz; echo x)" = /foo/barx
do_test "$($function_to_test foo foo; echo x)" = foox
do_test "$($function_to_test /fo /foo; echo x)" = /x ## Changed from x
do_test "$($function_to_test "/fo d/fo" "/fo d/foo"; echo x)" = "/fo dx"
if [ $failed -ne 0 ]; then echo $failed failures; return 1; fi
}