Рыба для пользователей bash
Это краткое руководство для тех, кто знаком с bash (или, в меньшей степени, другими оболочками, такими как zsh или ksh) и хочет понять, чем отличается рыба. Рыба намеренно несовместима с POSIX, и некоторые вещи, к которым вы привыкли, работают иначе.
Многие вещи похожи — обе оболочки в основном расширяют командные строки для выполнения команд, имеют конвейеры, перенаправления, переменные, шаблоны, используют вывод команд различными способами. Этот документ быстро покажет вам различия.
Замены команд
В рыбе замены команд обозначаются как (command) вместо $(command) (или `command`).
Кроме того, она разделяет их только по символам новой строки вместо $IFS. Если вы хотите разделить по чему-то другому, используйте разделение строк, разделение строк0 или сбор строк. Если эти команды используются в качестве последней команды в замене команды, созданные разделения переносятся. Например:
for i in (find . -print0 | string split0)
правильно обработает все возможные имена файлов.
Переменные
Рыба устанавливает и удаляет переменные с помощью команды set вместо VAR=VAL и declare и unset и export. set принимает параметры для определения области и экспортируемости переменной:
# Define $PAGER global and exported, so this is like ``export PAGER=less`` set -gx PAGER less # Define $alocalvariable only locally - like ``local alocalvariable=foo`` set -l alocalvariable foo
или для удаления переменных:
set -e PAGER
VAR=VAL операторы доступны в качестве переопределений среды:
PAGER=cat git log
Рыба не выполняет разбиение слов. После установки значения переменной, это значение остается неизменным, поэтому двойные кавычки при расширении переменных не являются такой же необходимостью, как в bash. 1
Например, вот bash
> foo="bar baz" > printf '"%s"\n' $foo # will print two lines, because we didn't double-quote, so the variable is split "bar" "baz"
А вот рыба:
> set foo "bar baz" > printf '"%s"\n' $foo # foo was set as one element, so it will be passed as one element, so this is one line "bar baz"
Все переменные являются «массивами» (мы используем термин «списки»), и расширение переменной расширяется до всех её элементов, где каждый элемент является собственным аргументом (как в bash'овском "${var[@]}") :
> set var "foo bar" banana > printf %s\n $var foo bar banana
Можно выбрать определенные элементы списка:
echo $list[5..7]
-
1 -
zsh также по умолчанию не выполняет разбиение слов (опция SH_WORD_SPLIT управляет этим)
Шаблоны (глобы)
Рыба поддерживает только * и ** шаблоны (и устаревший ? шаблон). Если шаблон не соответствует ни одному файлу, команда завершается ошибкой (как в bash'овском failglob), за исключением случаев, когда команда является for, set или count, или шаблон используется с переопределением среды (VAR=* command), в этом случае он расширяется до пустой строки (как в bash'овском nullglob варианте).
Глоббинг не происходит при расширении переменных, поэтому:
set foo "*" echo $foo
не найдет ни одного файла.
Нет опций для управления глоббингом, поэтому он всегда ведет себя так.
Кавычки
Рыба имеет два типа кавычек: "" и ''. В двойных кавычках переменные расширяются, а в одинарных — нет.
Нет $'', вместо этого последовательности, которые должны преобразовываться, преобразовываются при отсутствии кавычек:
> echo a\nb a b
Обработка строк
В рыбе нет ${foo%bar}, ${foo#bar} и ${foo/bar/baz}. Вместо этого обработка строк выполняется встроенной командой string.
Специальные переменные
Некоторые переменные bash и их аналоги в рыбе:
-
$*,$@,$1и так далее:$argv -
$?:$status -
$$:$fish_pid -
$#: Нет переменной, используйте вместо этогоcount $argv -
$!:$last_pid -
$0:status filename -
$-: В основномstatus is-interactiveиstatus is-login
Замена процессов
Вместо <(command) рыба использует (command | psub). Нет эквивалента >(command).
Обратите внимание, что оба эти приема являются bash-истическими и большинство операций можно легко выразить без них. Например, вместо:
source (command | psub)
просто используйте:
command | source
так как функция source рыбы может читать из стандартного ввода.
Встроенные документы
В рыбе нет <<EOF «встроенных документов». Вместо:
cat <<EOF some string some more string EOF
используйте:
printf %s\n "some string" "some more string"
или:
echo "some string some more string"
Кавычки следуют через новые строки.
Тест (test, [, [[)
Рыба имеет совместимую с POSIX встроенную функцию test или [. Нет [[, и test не принимает == как синоним =. Однако она может сравнивать числа с плавающей точкой.
set -q может использоваться для определения того, существует ли переменная или имеет ли она определенное количество элементов (set -q foo[2]).
Арифметическое расширение
В рыбе нет $((i+1)) арифметического расширения, вычисления обрабатываются с помощью встроенной команды math:
math $i + 1
Она может обрабатывать числа с плавающей точкой:
> math 5 / 2 2.5
Подсказки
Рыба не использует переменные $PS1, $PS2 и так далее. Вместо этого подсказка — вывод функции fish_prompt, плюс функция fish_mode_prompt, если включен видо-режим, и функция fish_right_prompt для правой подсказки.
Например, вот относительно простая bash подсказка:
# <$HOSTNAME> <$PWD in blue> <Prompt Sign in Yellow> <Rest in default light white> export PS1='\h\[\e[1;34m\]\w\[\e[m\] \[\e[1;32m\]\$\[\e[m\] '
и приблизительный эквивалент в рыбе:
function fish_prompt
set -l prompt_symbol '$'
fish_is_root_user; and set prompt_symbol '#'
echo -s $hostname (set_color blue) (prompt_pwd) \
(set_color yellow) $prompt_symbol (set_color normal)
end
Это демонстрирует некоторые различия:
- Рыба предоставляет функцию set_color для форматирования текста. Она может использовать 16 именованных цветов и последовательности RGB (так что вы также можете использовать
set_color 5555FF) - Вместо введения специфических эскейпов, как
\hдля имени хоста, подсказка представляет собой просто функцию, поэтому вы можете использовать переменные, например$hostname. - Рыба предлагает вспомогательные функции для добавления элементов в подсказку, например, fish_vcs_prompt для отображения систем контроля версий (git, mercurial, svn) и prompt_pwd для отображения сокращенного $PWD (домашний каталог пользователя становится
~, и любой компонент пути сокращается).
По умолчанию подсказка достаточно функциональна, и ее код можно прочитать с помощью type fish_prompt.
В рыбе нет $PS2 для продолжения строк, вместо этого строки отступают, чтобы показать, что командная строка еще не завершена.
Блоки и циклы
Конструкции блоков в рыбе выглядят немного иначе. Все они начинаются со слова, заканчиваются end и не имеют второго слова начала:
for i in 1 2 3; do
echo $i
done
# becomes
for i in 1 2 3
echo $i
end
while true; do
echo Weeee
done
# becomes
while true
echo Weeeeeee
end
{
echo Hello
}
# becomes
begin
echo Hello
end
if true; then
echo Yes I am true
else
echo "How is true not true?"
fi
# becomes
if true
echo Yes I am true
else
echo "How is true not true?"
end
foo() {
echo foo
}
# becomes
function foo
echo foo
end
# (note that bash specifically allows the word "function" as an extension, but POSIX only specifies the form without, so it's more compatible to just use the form without)
В рыбе нет until. Используйте while not или while !.
Подоболочки
У bash есть функция под названием «подоболочки», где она запускает новый процесс оболочки для определенных задач. Эта оболочка будет независимой, и, например, любые изменения, которые она внесёт в переменные, не будут видны в основной оболочке.
Это включает в себя:
# A list of commands in `()` parentheses
(foo; bar) | baz
# Both sides of a pipe
foo | while read -r bar; do
# This variable will not be visible outside of the while loop.
VAR=VAL
# This background process will not be, either
baz &
done
Часто подоболочки путают с группировкой {}, которая не использует подоболочку. Для группировки можно использовать begin; end в рыбе:
(foo; bar) | baz
# when it should really have been:
{ foo; bar } | baz
# becomes
begin; foo; bar; end | baz
Конвейер будет просто выполнен в том же процессе, поэтому циклы while read могут устанавливать переменные за пределами цикла:
foo | while read bar
set -g VAR VAL
baz &
end
echo $VAR # will print VAL
jobs # will show "baz"
Подоболочки также часто путают с заменами команд, которые bash записывает как `command` или $(command), а рыба — как (command). Bash также использует подоболочки для их реализации.
Изоляцию обычно можно достичь, просто ограничив область действия переменных (с помощью set -l), но если вам действительно нужно запустить код в новой среде оболочки, вы всегда можете использовать fish -c 'your code here' для явного выполнения.
Встроенные команды и другие команды
К этому моменту становится ясно, что рыба делает больший упор на свои встроенные команды и внешние команды, а не на свой синтаксис. Вот некоторые полезные встроенные команды и их примерные аналоги в bash:
-
string - это заменяет большинство преобразований строк (
${i%foo}и т.д.) и также может использоваться вместоgrepиsedи т.п. -
math - это заменяет
$((i + 1))арифметику и также может работать с числами с плавающей точкой и некоторыми простыми функциями (синус и аналогичные). -
argparse - это может обрабатывать разбор опций сценария, для чего bash, вероятно, использовал бы
getopt(zsh предоставляетzparseopts). -
count может использоваться для подсчета вещей и, следовательно, заменяет
$#и может использоваться вместоwc. -
status предоставляет информацию о состоянии оболочки, например, является ли она интерактивной или каков текущий номер строки. Это заменяет
$-и$BASH_LINENOи другие переменные. -
seq(1)может использоваться в качестве замены для{1..10}расширения диапазонов. Если ваша ОС не поставляетseq, fish включает функцию замены.
© 2021 fish-shell developers
Licensed under the GNU General Public License, version 2.
https://fishshell.com/docs/3.3/fish_for_bash_users.html