| FISH-FOR-BASH-USERS(1) | fish-shell | FISH-FOR-BASH-USERS(1) |
نام (NAME)
fish-for-bash-users - راهنمای مهاجرت و تفاوتهای پوسته فیش برای کاربران بش
توضیحات (DESCRIPTION)
این راهنما برای ارائه یک دید کلی و سریع به کاربرانی است که از پوسته bash (یا با شدتی کمتر از سایر پوستهها مانند zsh یا ksh) به فیش مهاجرت کردهاند و میخواهند تفاوتهای آن را بشناسند. پوسته fish عمداً با استاندارد POSIX سازگار نیست و به همین دلیل برخی از مواردی که به آنها عادت دارید، در اینجا به شکلی متفاوت کار میکنند.
بسیاری از امکانات مشابه هستند - هر دو در اصل خطوط فرمان را برای اجرای دستورات بسط میدهند، دارای پایپها (لولهها)، تغییرمسیرها، متغیرها، الگوهای عام (globs) بوده و از خروجی دستورات به روشهای گوناگون بهره میبرند. این سند برای نمایش سریع تفاوتها نگاشته شده است.
جایگزینی دستورات (COMMAND SUBSTITUTIONS)
پوسته fish جایگزینی دستورات را به صورت $(command) یا (command) مینویسد، و نه به صورت بکتیک `command`.
علاوه بر این، فیش خروجی را به جای استفاده از متغیر $IFS فقط بر اساس خطوط جدید (newline) تفکیک میکند. چنانچه مایل به تفکیک بر پایه موارد دیگری هستید، از دستورات توکار string split, string split0 یا string collect استفاده کنید. اگر این موارد به عنوان آخرین دستور در یک جایگزینی دستور استفاده شوند، تفکیکهای ایجادشده توسط آنها به مرحله بعد منتقل میگردد. بنابراین:
for i in (find . -print0 | string split0)
تمام نامهای ممکن فایلها را به درستی پردازش خواهد کرد.
متغیرها (VARIABLES)
پوسته fish تعریف و حذف متغیرها را به جای عبارت VAR=VAL و مجموعهای از دستورات توکار مجزا نظیر declare، unset و export، با استفاده از دستور توکار set انجام میدهد. دستور set گزینههایی را برای تعیین محدوده دید (scope) و وضعیت صدور به محیط (export) یک متغیر میپذیرد:
# Define $PAGER *g*lobal and e*x*ported, # 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
پوسته fish تفکیک کلمات (word splitting) را انجام نمیدهد. هنگامی که متغیری روی مقداری تنظیم شد، آن مقدار به همان شکل باقی میماند؛ بنابراین قرار دادن بسط متغیر درون نقلقول دوتایی (گیومه مضاعف) الزامی که در bash دارد را در اینجا ندارد. [1]
برای نمونه، رفتار در bash به این صورت است:
> foo="bar baz" > printf '"%s"\n' $foo # will print two lines, because we didn't double-quote # this is word splitting "bar" "baz"
و در fish به این صورت:
> 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"
همه متغیرها «آرایه» هستند (در فیش از واژه «لیست» استفاده میشود)، و بسط یک متغیر به تمام عناصر آن بسط مییابد، به طوری که هر عنصر به عنوان یک آرگومان جداگانه عمل میکند (مشابه "${var[@]}" در bash):
> set var "foo bar" banana > printf %s\n $var foo bar banana
میتوان عناصر خاصی از یک لیست را انتخاب کرد:
echo $list[5..7]
آرگومانهای ارسالی به set عادی هستند، بنابراین میتوانید یک متغیر را با خروجی یک دستور مقداردهی کنید:
# Set lines to all the lines in file, one element per line set lines (cat file)
یا ترکیبی از مقادیر ثابت و خروجی دستورات:
> set numbers 1 2 3 (seq 5 8) 9 > printf '%s\n' $numbers 1 2 3 5 6 7 8 9
قرار دادن علامت = با دستور set غیرضروری و نادرست است - دستور set foo = bar متغیر "foo" را روی دو مقدار تنظیم میکند: "=" و "bar". همچنین دستور set foo=bar خطایی چاپ خواهد کرد.
برای اطلاعات بیشتر، مستندات متغیرهای پوسته (Shell variables) را ببینید.
- [1]
- پوسته zsh نیز بهطور پیشفرض تفکیک کلمات را انجام نمیدهد (گزینه SH_WORD_SPLIT این رفتار را کنترل میکند).
مقادیر پیشفرض متغیرها (VARIABLE DEFAULTS)
پوسته fish از ساختار ${my_variable:-fallback} برای فراهم کردن مقادیر پیشفرض برای متغیرهای تعریفنشده پشتیبانی نمیکند. در عوض، میتوانید با بررسی اینکه آیا متغیر تاکنون تنظیم شده است یا خیر، مقادیر پیشفرض را مشخص کنید:
# Ensure XDG_CONFIG_HOME is set or use a default value set -q XDG_CONFIG_HOME || set XDG_CONFIG_HOME $HOME/.config # now use XDG_CONFIG_HOME as normal
کاراکترهای عام (WILDCARDS / GLOBS)
پوسته fish از نظر نحوی فقط از الگوهای عام * و ** (و الگوی منسوخشده ?) پشتیبانی میکند. اگر یک الگوی عام تطابقی نیابد، دستور با شکست مواجه میشود (مشابه failglob در bash)، مگر اینکه دستور یکی از موارد for، set یا count باشد، یا اینکه الگو با بازنویسی متغیر محیطی (VAR=* command) به کار رود که در این صورت به هیچ مقداری بسط نمییابد (مانند گزینه nullglob در bash).
الگویابی روی متغیرهای بسطیافته صورت نمیگیرد، بنابراین:
set foo "*" echo $foo
هیچ فایلی را مطابقت نخواهد داد.
هیچ گزینهای برای کنترل رفتار الگویابی وجود ندارد، بنابراین رفتار آن همواره یکسان است.
الگوی ** فایلها را در زیرپوشهها نیز مطابقت میدهد. در سایر پوستهها این قابلیت معمولاً نیازمند فعالسازی از طریق گزینهای خاص مانند setopt globstar در bash است.
برخلاف bash، فیش پیوندهای نمادین (symlinks) را نیز دنبال میکند و نتایج را با ترتیب طبیعی (natural sort) مرتب میسازد، به گونهای که اعداد موجود به عنوان عدد با هم مقایسه میشوند. این به این معناست که برای نمونه، قطعات موسیقی را حتی اگر شمارههایی مثل 1 به جای 01 داشته باشند، به درستی مرتب میکند.
برای اطلاعات بیشتر، مستندات الگوهای عام (Wildcards) را ببینید.
نقلقول (QUOTING)
پوسته fish دو سبک نقلقول دارد: "" (گیومه مضاعف) و '' (گیومه تکی). متغیرها درون گیومه مضاعف بسط مییابند، اما هیچ چیزی درون گیومه تکی بسط پیدا نمیکند.
ساختار $'' وجود ندارد؛ در عوض توالیهایی که باید تبدیل شوند، هنگامی که درون گیومه نباشند تبدیل میگردند:
> echo a\nb a b
برای اطلاعات بیشتر، مستندات نقلقول (Quotes) را ببینید.
دستکاری رشتهها (STRING MANIPULATION)
پوسته fish فاقد ساختارهای ${foo%bar}، ${foo#bar} و ${foo/bar/baz} است. در عوض، عملیات دستکاری رشتهها توسط دستور توکار string انجام میپذیرد.
برای نمونه، جهت جایگزینی "bar" با "baz":
> string replace bar baz "bar luhrmann" baz luhrmann
همچنین میتواند رشتهها را تفکیک کند:
> string split "," "foo,bar" foo bar
تطبیق با عبارات باقاعده (Regex) به عنوان جایگزینی برای grep:
> echo bababa | string match -r 'aba$' aba
پر کردن رشتهها تا پهنای مشخص با کاراکترهای دلخواه (padding):
> string pad -c x -w 20 "foo" xxxxxxxxxxxxxxxxxfoo
تبدیل حروف رشته به کوچک یا بزرگ:
> string lower Foo foo > string upper Foo FOO
تکرار رشتهها، پیرایش فاصلهها (trim)، اسکیپ کردن رشتهها، یا چاپ طول و عرض رشته (بر حسب سلولهای ترمینال).
متغیرهای ویژه (SPECIAL VARIABLES)
برخی از متغیرهای bash و نزدیکترین معادل آنها در fish:
- متغیرهای $*، $@، $1 و موارد بعدی: $argv
- متغیر $?: معادل $status
- متغیر $$: معادل $fish_pid
- متغیر $#: متغیری وجود ندارد، به جای آن از count $argv استفاده کنید
- متغیر $!: معادل $last_pid
- متغیر $0: معادل status filename
- متغیر $-: عمدتاً معادل دستورات status is-interactive و status is-login
جایگزینی فرآیند (PROCESS SUBSTITUTION)
پوسته fish به جای ساختار <(command) از (command | psub) استفاده میکند. هیچ معادلی برای >(command) وجود ندارد.
توجه داشته باشید که هر دوی اینها قابلیتهای مختص بش (bashisms) هستند، و بیشتر اهداف را میتوان به راحتی بدون آنها محقق ساخت. برای مثال، به جای:
source (command | psub)
استفاده کنید از:
command | source
زیرا دستور توکار source در فیش میتواند مستقیماً از ورودی استاندارد (stdin) بخواند.
اسناد درجا (HEREDOCS)
پوسته fish از ساختار اسناد درجا یا همان «heredoc» به شکل <<EOF بهره نمیبرد. به جای:
cat <<EOF some string some more string EOF
از این دستور استفاده کنید:
printf %s\n "some string" "some more string"
یا:
echo "some string some more string" # or if you want the quotes on separate lines: echo "\ some string some more string\ "
گیومهها در خطوط جدید نیز امتداد پیدا میکنند.
کاری که «heredocs» انجام میدهند به شرح زیر است:
- 1.
- خواندن و تفسیر رشته متنی، با قواعدی ویژه، تا رسیدن به نشانگر پایانی. [2]
- 2.
- نوشتن رشته حاصل در یک فایل موقت.
- 3.
- آغاز به کار دستوری که سند درجا به آن متصل شده، به طوری که آن فایل موقت به عنوان ورودی استاندارد (stdin) به آن داده میشود.
این بدان معناست که ماهیت آن اساساً همانند خواندن از یک پایپ (لوله) است؛ بنابراین:
echo "foo" | cat
تا حد زیادی مشابه این دستور است:
cat <<EOF foo EOF
همانند اسناد درجا، دستور مورد استفاده باید آماده خواندن از ورودی استاندارد (stdin) باشد. گاهی این امر مستلزم کاربرد گزینههای ویژه است، و اغلب دادن نام فایل به صورت - این قابلیت را فعال میسازد.
برای نمونه:
echo "xterm rxvt-unicode" | pacman --remove - # is the same as (the `-` makes pacman read arguments from stdin) pacman --remove xterm rxvt-unicode
و در سایر پوستهها میتوانست به صورت زیر نوشته شود:
# This "-" is still necessary - the heredoc is *also* passed over stdin! pacman --remove - << EOF xterm rxvt-unicode EOF
بنابراین اسناد درجا صرفاً یک ویژگی نحوی کماهمیت (syntactic sugar) هستند که قوانین ویژه بسیاری را ایجاد میکنند؛ به همین سبب فیش فاقد آنها است. پایپها مفهومی کلیدی، سادهتر و با ترکیبپذیری مناسبتر به شمار میروند.
شما همچنین میتوانید چند ورودی را به یک دستور پایپ کنید، مانند این مورد:
{ cat packages1; echo fish; } | pacman --sync -
- [2]
- به عنوان مثال، عبارت "EOF" فقط یک توافق و سنت است؛ نشانگر پایانی میتواند هر رشته دلخواهی باشد و عبارتی مثل "THISISTHEEND" نیز کار میکند. همچنین استفاده از <<- نویسههای تب ابتدای خطوط را حذف میکند (اما سایر فاصلههای خالی را دستنخورده میگذارد)، بنابراین میتوانید خطوط را به داخل ببرید اما فقط با نویسه تب. جایگزینیها (متغیرها، دستورات) بهطور پیشفرض روی سند درجا انجام میشوند، مگر اینکه نشانگر پایان درون گیومه قرار داده شده باشد: cat << "EOF".
دستور آزمون (TEST - [, [[)
پوسته fish دارای دستور توکار test یا [ سازگار با استاندارد POSIX است. ساختار [[ در آن وجود ندارد و دستور test عبارت == را به عنوان مترادفی برای = قبول نمیکند. با این حال، فیش میتواند اعداد ممیز شناور (اعشاری) را مقایسه کند.
دستور set -q میتواند برای تشخیص اینکه آیا یک متغیر وجود دارد یا تعداد مشخصی عنصر دارد به کار رود (set -q foo[2]).
بسط محاسباتی (ARITHMETIC EXPANSION)
پوسته fish فاقد بسط محاسباتی $((i+1)) است، و محاسبات ریاضی توسط دستور توکار math انجام میپذیرد:
math $i + 1
برخلاف محاسبات ریاضی در bash، این دستور توانایی کار با اعداد ممیز شناور (اعشاری) را دارد:
> math 5 / 2 2.5
و توابعی کاربردی، از جمله برای مثلثات، در اختیار دارد:
> math cos 2 x pi 1
شما میتوانید مانند بالا آرگومانها را به صورت جداگانه یا درون گیومه به دستور math بفرستید. از آنجا که فیش از پرانتزهای () برای جایگزینی دستورات بهره میبرد، اگر بخواهید از آنها در عبارت خود استفاده کنید نقلقول کردن (قرار دادن درون گیومه) الزامی است:
> math '(5 + 2) * 4'
هر دو نماد * و x روشهای معتبری برای نگارش عملگر ضرب هستند، اما * به دلیل اینکه شبیه به کاراکتر عام (glob) به نظر میرسد، نیازمند قرارگیری درون گیومه است.
اعلانهای خط فرمان (PROMPTS)
پوسته fish از متغیرهای $PS1، $PS2 و نظایر آنها استفاده نمیکند. در عوض اعلان خط فرمان خروجی تابع fish_prompt است، بهعلاوه خروجی تابع fish_mode_prompt در صورتی که حالت vi فعال باشد. خروجی تابع fish_right_prompt نیز برای اعلان سمت راست صفحه نمایش به کار میرود.
به عنوان نمونه، این یک اعلان خط فرمان نسبتاً ساده در bash است:
# <$HOSTNAME> <$PWD in blue> <Prompt Sign in Yellow> <Rest in default light white> PS1='\h\[\e[1;34m\]\w\[\e[m\] \[\e[1;32m\]\$\[\e[m\] '
و این معادل تقریبی آن در fish است:
function fish_prompt
set -l prompt_symbol '$'
fish_is_root_user; and set prompt_symbol '#'
echo -s (prompt_hostname) \
(set_color blue) (prompt_pwd) \
(set_color yellow) $prompt_symbol (set_color --reset)
end
این چند تفاوت را نشان میدهد:
- پوسته fish دستور set_color را برای رنگی کردن متن فراهم میکند. این دستور میتواند ۱۶ رنگ نامگذاریشده و همچنین توالیهای RGB را به کار گیرد (بنابراین میتوانید از set_color 5555FF نیز استفاده کنید).
- به جای معرفی کدهای اسکیپ اختصاصی مانند \h برای نام میزبان، اعلان یک تابع است. برای دستیابی به اثری مانند \h، فیش توابع کمکی نظیر prompt_hostname را ارائه میدهد که نسخه کوتاهشدهای از نام میزبان را چاپ میکند.
- پوسته fish توابع کمکی دیگری را برای افزودن المانها به خط اعلان فراهم ساخته است، مانند fish_vcs_prompt برای افزودن وضعیت سیستمهای کنترل نسخه مرسوم (git، mercurial، svn) و prompt_pwd برای نمایش نسخه خلاصهشده $PWD (دایرکتوری خانگی کاربر به ~ تبدیل شده و اجزای مسیر کوتاه میشوند).
اعلان پیشفرض بسیار کامل است و کدهای آن با اجرای type fish_prompt قابل مشاهده است.
پوسته fish متغیر $PS2 را برای خطوط ادامهدار ندارد، در عوض خطوط را تورفته رها میکند تا نشان دهد خط فرمان هنوز پایان نیافته است.
بلوکها و حلقهها (BLOCKS AND LOOPS)
ساختارهای مسدودکننده و بلوکها در fish کمی متفاوت به نظر میرسند. همه آنها با یک کلمه آغاز میشوند، با کلمه 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
# (bash allows the word "function",
# but this is an extension)
پوسته fish ساختار until ندارد. به جای آن از while not یا while ! استفاده نمایید.
زیرپوستهها (SUBSHELLS)
پوسته Bash قابلیتی به نام «زیرپوسته» (subshell) دارد که طی آن، برای کارهایی مشخص یک فرآیند پوسته دیگر را راهاندازی میکند. آن پوسته مستقل خواهد بود و برای مثال هر تغییری که در متغیرها بدهد، در پوسته اصلی دیده نخواهد شد.
این موضوع شامل مواردی مانند اینها است:
# A list of commands in `()` parentheses
(foo; bar) | baz
# Both sides of a pipe
foo | while read -r bar; do
# This will not be visible outside of the loop.
VAR=VAL
# This background process will not be, either
baz &
done
پوسته fish در حال حاضر دارای زیرپوسته نیست. شما باید راهکار دیگری پیدا کنید. ایزولهسازی معمولاً با تعیین محدوده متغیرها (با دستور set -l) امکانپذیر است، اما اگر واقعاً نیاز به اجرای کد در محیط پوستهای نو دارید، میتوانید برای انجام صریح آن از دستور fish -c 'your code here' استفاده فرمایید.
زیرپوستههای دارای پرانتز () معمولاً با گروهبندی براکتی {} که از زیرپوسته استفاده نمیکند اشتباه گرفته میشوند. وقتی که فقط نیاز به گروهبندی دارید، میتوانید در fish از 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) نگاشته شده و در fish به شکل $(command) یا (command) نوشته میشود. پوسته Bash برای پیادهسازی آنها نیز از زیرپوستهها استفاده میکند.
دستورات توکار و سایر دستورات (BUILTINS AND OTHER COMMANDS)
تاکنون آشکار گردیده که پوسته fish بیش از آنکه بر روی سینتکس تمرکز کند، تمرکز بسیار بیشتری را بر روی دستورات توکار و دستورات خارجی معطوف کرده است. در اینجا برخی از دستورات توکار سودمند و معادل تقریبی آنها در bash ذکر شده است:
- دستور string - جایگزین اغلب تبدیلات رشتهای (${i%foo} و نظایر آن) میشود و همچنین میتواند به جای grep، sed و مانند اینها استفاده گردد.
- دستور math - جایگزین محاسبات حسابی $((i + 1)) میشود و علاوه بر این میتواند با اعداد اعشاری و برخی توابع ساده (سینوس و همتایانش) کار کند.
- دستور argparse - توانایی پردازش و مدیریت گزینههای یک اسکریپت را دارد؛ کاری که bash برای آن احتمالاً از getopt بهره میبرد (و zsh دستور zparseopts را ارائه میدهد).
- دستور count - میتواند برای شمارش اقلام استفاده شود و بنابراین جایگزین $# شده و میتواند به جای wc نیز استفاده شود.
- دستور status - اطلاعاتی درباره وضعیت پوسته، برای مثال تعاملی بودن آن یا شماره خط فعلی، ارائه میدهد. این دستور جایگزین متغیرهای $-، $BASH_LINENO و سایر متغیرها است.
- دستور seq(1) - میتواند به عنوان جایگزینی برای بسط بازهای {1..10} استفاده شود. چنانچه سیستمعامل شما حاوی دستور seq نباشد، فیش یک تابع جایگزین درون خود گنجانده است.
سایر امکانات (OTHER FACILITIES)
پوسته Bash دارای گزینههای set -x یا set -o xtrace برای چاپ همه دستوراتی است که اجرا میشوند. در fish، این ویژگی با مقداردهی متغیر محیطی fish_trace فعال میگردد.
یا اگر هدف شما پروفایل (profile) کردن این است که هر خط از اسکریپت چه مدت زمان صرف میکند، میتوانید از دستور fish --profile استفاده کنید - به صفحه راهنمای دستور fish(1) مراجعه فرمایید.
نویسندگان (AUTHORS)
توسعهدهندگان پوسته فیش (fish-shell developers)
حق نشر (COPYRIGHT)
توسعهدهندگان پوسته فیش (fish-shell developers)
همچنین ببینید (SEE ALSO)
پایگاه وب رسمی پوسته فیش: https://fishshell.com
| 2026-09-07 | 4.9 |