Bash: различия между версиями

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
imported>VitalikBot
м Обновление шаблона {{improve}}; langs: en,en
imported>Jet Jerry
 
Строка 1: Строка 1:
= {{-en-}} =
{{Другие значения|Bash (значения)}}
{{Омонимы|en|2}}
{{Программа
| название                  = GNU Bourne-Again SHell
| логотип                    = Gnu-bash-logo.svg
| снимок экрана              = Bash screenshot.png
| подпись                    = Типичный сеанс в bash
| тип                        = [[Оболочка операционной системы]], [[командная оболочка UNIX]]
| автор                      = [[Фокс, Брайан|Брайан Фокс]]
| разработчик                = Чет Рэйми
| написана на                = [[Си (язык программирования)|Си]]
| интерфейс                  =
| движок                    =
| операционные системы      = {{Немаркированный список| [[Linux]] | [[Unix-подобная операционная система|Unix-подобные]] | [[macOS]] | [[Windows]] | [[Android]] | [[Solaris]] }}
| аппаратная платформа      = [[GNU]]
| языки интерфейса          = Многоязычный ([[gettext]])
| первый выпуск              = {{Start date and age|1989|06|08|df=yes}}
| последняя версия          =
| дата последней версии      =
| репозиторий                =
| читаемые форматы файлов    =
| создаваемые форматы файлов =
| состояние                  =
| лицензия                  = {{Plainlist|
*  v.4.0+: [[GNU General Public License#GPL v3|GPL 3.0+]]<ref>
{{Cite web
| access-date  = 2025-08-08
| archive-date = 2019-04-26
| archive-url  = https://web.archive.org/web/20190426210620/http://www.gnu.org/software/bash/
| publisher    = [[GNU Project]]
| quote        = Bash is free software, distributed under the terms of the [GNU] General Public License as published by the Free Software Foundation, version 3 of the License (or any later version).
| title        = GNU Bash
| url          = https://www.gnu.org/software/bash/
| url-status  = live
| website      = [[Free Software Foundation, Inc.]]
}}
</ref>
*  v.1.11 – v.3.2: [[GNU General Public License#GPL v2|GPL 2.0+]]<ref>
{{Cite web
| access-date  = 2025-08-08
| archive-date = 2021-10-15
| archive-url  = https://web.archive.org/web/20211015233550/http://www.oldlinux.org/Linux.old/bin/old/bash-1.11/
| quote        = See test.c for GPL-2.0-or-later
| title        = bash-1.11
| url          = https://www.oldlinux.org/Linux.old/bin/old/bash-1.11/
| website      = oldlinux.org
}}
</ref>
*  v.0.99 – v.1.05: [[GNU General Public License#GPL v1|GPL 1.0+]]<ref
name="bashfaq061">
{{Cite web
| access-date  = 2025-08-08
| archive-date = 2021-03-02
| archive-url  = https://web.archive.org/web/20210302212811/https://mywiki.wooledge.org/BashFAQ/061
| title        = BashFAQ/061: Is there a list of which features were added to specific releases (versions) of Bash?
| url          = https://mywiki.wooledge.org/BashFAQ/061
| url-status  = live
| website      = wooledge.org
}}
</ref><ref>{{Cite web
| access-date  = 2025-08-08
| archive-date = 2021-05-06
| archive-url  = https://web.archive.org/web/20210506191114/http://www.oldlinux.org/Linux.old/bin/old/bash-1.05/
| title        = bash-1.05
| url          = https://www.oldlinux.org/Linux.old/bin/old/bash-1.05/
| website      = oldlinux.org
}}
</ref><ref>{{Cite web
| access-date = 2025-08-08
| title      = Is there a way to download the presumably initial bash source bash-0.99?
| url        = https://unix.stackexchange.com/questions/243375/is-there-a-way-to-download-the-presumably-initial-bash-source-bash-0-99
| website    = unix.stackexchange.com
}}</ref>
}}
| сайт                      = {{URL|www.gnu.org/software/bash/}}
| кандидат в релизы          =
| дата кандидата в релизы    =
| тестовая версия            = 5.2-beta
| дата тестовой версии      = [[13 апреля]] [[2022 год]]а
| бета-версия                =
| дата бета-версии          =
| альфа-версия              =
| дата альфа-версии          =
}}
'''Bash''' (от {{lang-en|'''B'''ourne '''a'''gain '''sh'''ell}}, [[каламбур]] {{lang-en2|«Born again» shell}} — «возрождённый» shell) — усовершенствованная и модернизированная вариация [[командная оболочка UNIX|командной оболочки]] [[Bourne shell]]. Одна из наиболее популярных современных разновидностей командной оболочки [[UNIX]]. Особенно популярна в среде [[Linux]], где она часто используется в качестве предустановленной командной оболочки.
 
Представляет собой командный процессор, работающий, как правило, в интерактивном режиме в текстовом окне. Bash также может читать команды из файла, который называется ''[[скрипт]]ом'' (или ''сценарием''). Как и все Unix-оболочки, он поддерживает автодополнение имён файлов и каталогов, подстановку вывода результата команд, переменные, контроль над порядком выполнения, операторы ветвления и цикла. Ключевые слова, синтаксис и другие основные особенности языка были заимствованы из [[Bourne shell|sh]]. Другие функции, например, история, были скопированы из [[csh]] и [[Korn shell|ksh]]. Bash в основном соответствует стандарту [[POSIX]], но с рядом расширений<ref>{{Cite web|url=https://www.oreilly.com/openbook/debian/book/ch13_01.html|title=Learning Debian GNU/Linux|author=William McCarty|website=|subtitle=13. Conquering the BASH Shell|date=1999-10-06|publisher=O'Reilly Media|lang=en|access-date=2018-12-06|archive-date=2017-11-09|archive-url=https://web.archive.org/web/20171109094032/http://www.oreilly.com/openbook/debian/book/ch13_01.html|url-status=live}}</ref>.
 
Название «bash» является [[акроним]]ом от {{lang-en|Bourne-again-shell}} («ещё-одна-командная-оболочка-Борна») и представляет собой игру слов: Bourne-shell — одна из популярных разновидностей командной оболочки для UNIX (sh), автором которой является [[Борн, Стивен|Стивен Борн]] ([[1978]]), усовершенствована в [[1987 год]]у [[Фокс, Брайан|Брайаном Фоксом]]. Фамилия Bourne (Борн) перекликается с английским словом {{lang-en2|born}}, означающим «родившийся», отсюда: рождённая-вновь-командная оболочка.
 
В сентябре 2014 года в bash была обнаружена широко эксплуатируемая уязвимость [[Bashdoor]].
 
== История ==
Функциональность сценариев оболочки изначально появилась в файлах, называемых «[[RUNCOM|runcom]]» в честь появившегося в [[1963 год]]у [[Макрокоманда|макропроцессора]] с тем же названием.
Суффикс «rc» — это сокращение от «runcom».<ref>
{{Cite web
| access-date  = 2025-08-08
| archive-date = 2010-06-10
| archive-url  = https://web.archive.org/web/20100610011504/http://kb.iu.edu/data/abnd.html
| date        = 2009-02-05
| publisher    = Indiana University
| title        = In Unix, what do some obscurely named commands stand for?
| url          = https://kb.iu.edu/data/abnd.htmliu.edu_09
| website      = iu.edu
}}</ref>
Термин «[[Оболочка операционной системы|оболочка]]» был придуман Луи Пузеном в [[1964 год|1964]] или [[1965 год]]у и появился в его статье [[1965 год]]а «Оболочка, глобальный инструмент для вызова и цепочки процедур в системе», в которой описываются многие функции, позже обнаруженные во многих оболочках Unix.<ref>
{{Cite web
| author  = Louis Pouzin
| date    = 2000-11-25
| title  = The Origin of the Shell
| url    = https://multicians.org/shell.html
| website = multicians.org
}}
</ref><ref>
{{Cite web
| title  = The SHELL, A Global Tool for Calling and Chaining Procedures in the System
| url    = https://people.csail.mit.edu/saltzer/Multics/Multics-Documents/MDN/MDN-4.pdf
| website = mit.edu
}}
</ref>
Стандарт [[ASCII]] для [[Набор символов|кодировки символов]] был определен в [[1969 год]]у в документе под названием [[RFC]] 20.<ref>
{{Cite web
| access-date = 2025-08-08
| date        = 1969-10-16
| first      = Vint
| last        = Cerf
| publisher  = UCLA, Network Working Group
| title      = ASCII Format for Network Interchange
| url        = https://datatracker.ietf.org/doc/html/rfc20
| website    = ietf.org
}}</ref>
 
=== Хронология ===
Ниже перечислены значимые события в истории Bash :
 
{| class = "wikitable sortable collapsible collapsed"
! Дата
! Событие
|-
! [[10 января]] [[1988 год|1988]]
|
[[Фокс, Брайан|Брайан Фокс]] начал [[Программирование|разрабатывать]] Bash после того, как [[Столлман, Ричард Мэттью|Ричард Столлман]] был недоволен отсутствием прогресса, достигнутого предыдущим разработчиком.<ref name="comp.unix_88">
{{Cite newsgroup
| access-date  = 2021-12-28
| archive-date = 2021-12-28
| archive-url  = https://web.archive.org/web/20211228023030/https://groups.google.com/g/comp.unix.questions/c/iNjWwkyroR8/m/yedr9yDWSuQJ
| date        = 1988-02-10
| last1        = Stallman
| first1      = Richard
| last2        = Ramey
| first2      = Chet
| message-id  = 2362@mandrill.CWRU.Edu
| newsgroup    = comp.unix.questions
| quote        = For a year and a half, the GNU shell was "just about done". The author made repeated promises to deliver what he had done, and never kept them. Finally I could no longer believe he would ever deliver anything. So Foundation staff member Brian Fox is now implementing an imitation of the Bourne shell.
| title        = GNU + BSD = ?
| url          = https://groups.google.com/g/comp.unix.questions/c/iNjWwkyroR8/m/yedr9yDWSuQJ
| url-status  = live
| website      = google.com
}}
</ref>
Столлман и [[Фонд свободного программного обеспечения|FSF]] считали, что свободная оболочка, способная запускать существующие сценарии оболочки, настолько важна для полностью свободной системы, построенной на коде BSD и GNU, что это был один из немногих проектов, которые они финансировали сами.
Fox выполнял эту работу в качестве сотрудника FSF.<ref name =comp.unix_88/><ref>
{{Cite web
| access-date  = 2025-08-08
| archive-date = 2011-04-24
| archive-url  = https://web.archive.org/web/20110424064815/https://www.gnu.org/gnu/thegnuproject.html
| date        = 2010-10-03
| first        = Richard
| last        = Stallman
| publisher    = [[GNU Project]]
| quote        = Free Software Foundation employees have written and maintained a number of GNU software packages. Two notable ones are the C library and the shell. ... We funded development of these programs because the GNU Project was not just about tools or a development environment. Our goal was a complete operating system, and these programs were needed for that goal.
| title        = About the GNU Project
| url          = https://www.gnu.org/gnu/thegnuproject.html
| url-status  = live
| website      = [[Free Software Foundation, Inc.]]
}}
</ref>
|-
! [[8 июня]] [[1989 год|1989]]
|
Фокс выпустил Bash как бета-версию 0.99.<ref>
{{Cite newsgroup
| access-date  = 2010-10-28
| archive-date = 2013-05-04
| archive-url  = https://web.archive.org/web/20130504075535/http://groups.google.com/group/gnu.announce/msg/a509f48ffb298c35?hl=en
| date        = 1989-06-08
| first1      = Brian
| first2      = Leonard H.
| last1        = Fox
| last2        = Tower Jr.
| newsgroup    = gnu.announce
| title        = Bash is in beta release!
| url          = https://groups.google.com/group/gnu.announce/msg/a509f48ffb298c35?hl=en
| url-status  = live
| website      = google.com
}}</ref>
Лицензия — GPL 1.0+.
«Помимо поддержки обратной совместимости для сценариев, Bash включил в себя функции оболочек Korn и C.
Вы найдете историю команд, редактирование командной строки, стек каталогов (pushd и popd), множество полезных переменных окружения, автодополнение команд и многое другое.»<ref>
{{Cite web
| date      = 2011-12-09
| publisher = IBM
| title    = Evolution of shells in Linux
| url      = https://developer.ibm.com/tutorials/l-linux-shells/
| website  = ibm.com
}}
</ref>
В конечном итоге, он стал поддерживать «регулярные выражения (аналогично Perl) и ассоциативные массивы».
|-
! [[1991 год|1991]]
|
Bash имеет историческое значение как одна из первых программ, портированных на [[Торвальдс, Линус|Линусом Торвальдсом]], наряду с GNU Compiler ([[GNU Compiler Collection|GCC]]).<ref>
{{Cite newsgroup
| access-date  = 2025-08-08
| date        = 1991-08-26
| first        = Linus
| last        = Torvalds
| newsgroup    = comp.os.minix
| quote        = To make things really clear - yes I can run gcc on it, and bash, and most of the gnu [bin/file]utilities
| title        = What would you like to see most in Minix?
| url          = https://groups.google.com/group/comp.os.minix/msg/b813d52cbc5a044b
| website      = google.com
}}</ref>
|-
! [[1992 год|1992]] ~ [[1994 год|1994]]
|
Брайан Фокс ушел с поста основного сопровождающего где-то между серединой [[1992 год]]а<ref>
{{Cite newsgroup
| access-date  = 2010-10-28
| archive-date = 2021-03-02
| archive-url  = https://web.archive.org/web/20210302213455/https://groups.google.com/forum/
| date        = 1993-04-20
| message-id  = gnusenet930421bulletin@prep.ai.mit.edu
| newsgroup    = gnu.announce
| title        = January 1993 GNU's Bulletin
| url          = https://groups.google.com/group/gnu.misc.discuss/msg/4f42c739cd7e8bd8
| url-status  = live
| website      = google.com
}}
</ref>
и серединой [[1994 год]]а.<ref>
{{Cite web
| access-date  = 2008-11-13
| archive-date = 2008-12-05
| archive-url  = https://web.archive.org/web/20081205082152/http://www.linuxjournal.com/article/2800
| date        = 1994-08-01
| first        = Chet
| last        = Ramey
| publisher    = [[Linux Journal]]
| title        = Bash – the GNU shell (Reflections and Lessons Learned)
| url          = https://www.linuxjournal.com/article/2800#N0xa50890.0xb46380
| url-status  = live
| website      = linuxjournal.com
}}
</ref><ref>
{{Citation
| access-date  = 2010-10-31
| archive-date = 2012-07-20
| archive-url  = https://web.archive.org/web/20120720124341/http://www.scribd.com/doc/40556434/2010-10-31-Chet-Ramey-Early-Bash-Dates
| date        = 2010-10-31
| first        = Chet
| last        = Ramey
| title        = Dates in your Computerworld interview
| url          = https://www.scribd.com/doc/40556434/2010-10-31-Chet-Ramey-Early-Bash-Dates
| url-status  = live
| website      = scribd.com
}}
</ref>
Его обязанности были переданы другому раннему участнику, Чету Рэйми.<ref name =bash-top/><ref>
{{Multiref2
|
{{Cite newsgroup
| access-date  = 2010-11-01
| archive-date = 2012-11-10
| archive-url  = https://web.archive.org/web/20121110194014/http://groups.google.com/group/gnu.bash.bug/msg/1fc7b688f5d44438?hl=en
| date        = 1989-06-12
| last        = Ramey
| first        = Chet
| newsgroup    = gnu.bash.bug
| title        = Bash 0.99 fixes & improvements
| url          = https://groups.google.com/group/gnu.bash.bug/msg/1fc7b688f5d44438?hl=en
| url-status  = live
| website      = google.com
}}
|
{{Cite newsgroup
| access-date  = 2010-10-30
| archive-date = 2012-11-10
| archive-url  = https://web.archive.org/web/20121110194034/http://groups.google.com/group/gnu.bash.bug/msg/072a03645663caea?hl=en
| date        = 1989-07-24
| last        = Ramey
| first        = Chet
| newsgroup    = gnu.bash.bug
| title        = Some bash-1.02 fixes
| url          = https://groups.google.com/group/gnu.bash.bug/msg/072a03645663caea?hl=en
| url-status  = live
| website      = google.com
}}
|
{{Cite newsgroup
| access-date  = 2010-10-30
| archive-date = 2012-11-10
| archive-url  = https://web.archive.org/web/20121110194052/http://groups.google.com/group/gnu.bash.bug/msg/e6112ccc8866e2f4?hl=en
| date        = 1990-03-02
| last        = Fox
| first        = Brian
| newsgroup    = gnu.bash.bug
| title        = Availability of bash 1.05
| url          = https://groups.google.com/group/gnu.bash.bug/msg/e6112ccc8866e2f4?hl=en
| url-status  = live
| website      = google.com
}}
}}</ref><ref name="computerworld_08"/><ref name="goftw2015"/>
С тех пор Bash стал самой популярной интерактивной оболочкой по умолчанию среди основных дистрибутивов GNU/Linux, таких как [[Fedora Linux|Fedora]], [[Debian]] и [[openSUSE]], а также среди их производных и конкурентов.<ref>
{{Cite book
| access-date  = 6 June 2016
| archive-date = 2 March 2021
| archive-url  = https://web.archive.org/web/20210302212409/https://books.google.com/books?id=2P3zBgAAQBAJ&q=%22most+popular%22+linux+shell&pg=PA5
| date        = April 2015
| edition      = 3rd
| first1      = Christine
| first2      = Richard
| isbn        = 978-1-119-02122-3
| last1        = Bresnahan
| last2        = Blum
| page        = 5
| publisher    = John Wiley & Sons, Inc.
| quote        = In Linux, most users run bash because it is the most popular shell.
| title        = CompTIA Linux+ Powered by Linux Professional Institute Study Guide: Exam LX0-103 and Exam LX0-104
| url          = https://books.google.com/books?id=2P3zBgAAQBAJ&q=%22most+popular%22+linux+shell&pg=PA5
| url-status  = live
}}
</ref><ref>
{{Cite book
| access-date  = 6 June 2016
| archive-date = 2 March 2021
| archive-url  = https://web.archive.org/web/20210302212410/https://books.google.com/books?id=tIjrVYbZmUAC&q=bash+most+popular+unix+shell&pg=PA363
| date        = February 2006
| first1      = Arman
| first2      = Michael
| isbn        = 978-0-7821-5277-7
| last1        = Danesh
| last2        = Jang
| page        = 363
| publisher    = John Wiley & Sons, Inc.
| quote        = The Bourne Again Shell (bash) is the most common shell installed with Linux distributions.
| title        = Mastering Linux
| url          = https://books.google.com/books?id=tIjrVYbZmUAC&q=bash+most+popular+unix+shell&pg=PA363
| url-status  = live
}}
</ref>
|-
! [[26 января]] [[1994 год|1994]]
|
Debian — первый релиз.
Bash является оболочкой по умолчанию для интерактивного и неинтерактивного взаимодействия.<ref name="debian.org_shell">
{{Cite web
| title  = Debian Wiki: Shell
| url    = https://wiki.debian.org/Shell
| website = debian.org
}}</ref>
|-
! [[31 декабря]] [[1996 год|1996]]
|
Чет Рэйми выпустил bash 2.0.
Лицензия — GPL 2.0+.
|-
! [[5 июня]] [[1997 год|1997]]
|
Вышел Bash 2.01.
|-
! [[18 апреля]] [[1998 год|1998]]
|
Вышел Bash 2.02.
|-
! [[19 февраля]] [[1999 год|1999]]
|
Вышел Bash 2.03.
|-
! [[21 марта]] [[2000 год|2000]]
|
Вышел Bash 2.04.
|-
! [[14 сентября]] [[2000 год|2000]]
|
Список рассылки Bug-bash существует.<ref>
{{Cite mailing list
| access-date  = 2025-08-08
| date        = 2000-09-14
| first        = Chet
| last        = Ramey
| mailing-list = bug-bash
| publisher    = [[GNU Project]]
| title        = Re: Line-Edit mode is lost if "set -o vi" is in any files sourced on login.
| url          = https://lists.gnu.org/archive/html/bug-bash/2000-09/msg00000.html
}}
</ref>
|-
! [[9 апреля]] [[2001 год|2001]]
|
Вышел Bash 2.05.<ref>
{{Cite mailing list
| access-date  = 2025-08-08
| date        = 2001-04-09
| first        = Chet
| last        = Ramey
| mailing-list = bug-bash
| publisher    = [[GNU Project]]
| title        = Bash-2.05 available for FTP
| url          = https://lists.gnu.org/archive/html/bug-bash/2001-04/msg00047.html
}}
</ref>
|-
! [[2003 год|2003]]
|
Начиная с OS X 10.3 Panther, Bash стал оболочкой по умолчанию в операционных системах Apple (то есть macOS).<ref>[https://www.google.com/books/edition/Essential_Mac_OS_X_Panther_Server_Admini/zrI-U0KWj3cC?hl=en&gbpv=1&dq=bash&pg=PA189&printsec=frontcover Essential Mac OS S Panther Server Administration, pg 189]
</ref><ref>
{{Cite book
| access-date  = 8 August 2025
| archive-date = 2 March 2021
| archive-url  = https://web.archive.org/web/20210302212410/https://books.google.com/books?id=dwIRERUpQPEC&q=bash+most+popular+unix+shell&pg=PA6
| date        = April 2005
| first1      = Eric
| first2      = John C.
| first3      = Micah
| isbn        = 978-0-7645-9791-6
| last1        = Foster-Johnson
| last2        = Welch
| last3        = Anderson
| page        = 6
| publisher    = John Wiley & Sons, Inc.
| quote        = Bash is by far the most popular shell and forms the default shell on Linux and Mac OSX systems.
| title        = Beginning Shell Scripting
| url          = https://books.google.com/books?id=dwIRERUpQPEC&q=bash+most+popular+unix+shell&pg=PA6
| url-status  = live
}}
</ref>
Он также был доступен в OS X 10.2 Jaguar, где оболочкой по умолчанию был tcsh.
|-
! [[27 июля]] [[2004 год|2004]]
|
Вышел Bash 3.0.<ref>
{{Cite mailing list
| access-date  = 2025-08-08
| mailing-list = bug-bash
| publisher    = [[GNU Project]]
| title        = Bash-3.0 available for FTP
| url          = https://lists.gnu.org/archive/html/bug-bash/2004-07/msg00255.html
}}
</ref>
|-
! [[9 декабря]] [[2005 год|2005]]
|
Вышел Bash 3.1.<ref>
{{Cite mailing list
| access-date  = 2025-08-08
| mailing-list = bug-bash
| publisher    = [[GNU Project]]
| title        = Bash-3.1 released
| url          = https://lists.gnu.org/archive/html/bug-bash/2005-12/msg00018.html
}}
</ref>
|-
! [[12 октября]] [[2006 год|2006]]
|
Вышел Bash 3.2.<ref>
{{Cite mailing list
| access-date  = 2025-08-08
| mailing-list = bug-bash
| publisher    = [[GNU Project]]
| title        = Bash-3.2 available for FTP
| url          = https://lists.gnu.org/archive/html/bug-bash/2006-10/msg00057.html
}}
</ref>
Лицензия — GPL 2.0+.
|-
! [[2006 год|2006]]
|
В Ubuntu в качестве оболочки по умолчанию вместо bash используется dash.
|-
! [[20 февраля]] [[2009 год|2009]]
|
Вышел Bash 4.0<ref>
{{Cite mailing list
| access-date  = 2025-08-08
| mailing-list = bug-bash
| publisher    = [[GNU Project]]
| title        = Bash-4.0 available for FTP
| url          = https://lists.gnu.org/archive/html/bug-bash/2009-02/msg00164.html
}}
</ref>
Лицензия — GPL 3.0+.
|-
! [[2 января]] [[2010 год|2010]]
|
Вышел Bash 4.1.<ref>
{{Cite mailing list
| access-date  = 2025-08-08
| mailing-list = bug-bash
| publisher    = [[GNU Project]]
| title        = Bash-4.1 available for FTP
| url          = https://lists.gnu.org/archive/html/bug-bash/2010-01/msg00000.html
}}
</ref>
|-
! [[14 февраля]] [[2011 год|2011]]
|
Вышел Bash 4.2.<ref>
{{Cite mailing list
| access-date  = 2025-08-08
| mailing-list = bug-bash
| publisher    = [[GNU Project]]
| title        = Bash-4.2 available for FTP
| url          = https://lists.gnu.org/archive/html/bug-bash/2011-02/msg00134.html
}}
</ref>
|-
! [[2012 год|2012]]
|
В [[Solaris]] 11, «оболочкой пользователя по умолчанию является Bourne-again (bash) shell.»<ref>
{{Cite web
| access-date  = 2025-08-08
| archive-date = 2018-06-12
| archive-url  = https://web.archive.org/web/20180612144748/https://docs.oracle.com/cd/E23824_01/html/E24456/userenv-1.html
| publisher    = [[Oracle Corporation]]
| title        = User Environment Feature Changes
| url          = https://docs.oracle.com/cd/E23824_01/html/E24456/userenv-1.html
| url-status  = live
| website      = oracle.com
}}
</ref>
|-
! [[27 февраля]] [[2014 год|2014]]
|
Вышел Bash 4.3.<ref>
{{Cite mailing list
| access-date  = 2025-08-08
| mailing-list = bug-bash
| publisher    = [[GNU Project]]
| title        = Bash-4.3 available for FTP
| url          = https://lists.gnu.org/archive/html/bug-bash/2014-02/msg00081.html
}}
</ref>
|-
! [[8 сентября]] [[2014 год|2014]]
|
[[Bashdoor|Bashdoor (Shellshock)]].<ref>
{{Cite web
| access-date = 2025-08-08
| quote      = GNU Bash through 4.3 processes trailing strings after function definitions in the values of environment variables, which allows remote attackers to execute arbitrary code via a crafted environment, as demonstrated by vectors involving the ForceCommand feature in OpenSSH sshd, the mod_cgi and mod_cgid modules in the Apache HTTP Server, scripts executed by unspecified DHCP clients, and other situations in which setting the environment occurs across a privilege boundary from Bash execution, aka "ShellShock."
| title      = CVE-2014-6271
| url        = https://www.cve.org/CVERecord?id=CVE-2014-6271
| website    = cve.org
}}
</ref><ref>
{{Cite web
| access-date = 2025-08-08
| title      = CVE-2014-7169
| url        = https://www.cve.org/CVERecord?id=CVE-2014-7169
| website    = cve.org
}}
</ref>
Патчи для исправления ошибок были выпущены вскоре после того, как ошибки были обнаружены.<ref>
{{Cite mailing list
| access-date  = 2025-08-08
| mailing-list = bug-bash
| publisher    = [[GNU Project]]
| title        = Bash 3.0 Official Patch 1
| url          = https://lists.gnu.org/archive/html/bug-bash/2004-09/msg00083.html
}}
</ref>
|-
! [[2015 год|2015]]
|
[[Termux]] и другие приложения для эмуляции терминала обеспечивают доступность Bash на [[Android]].
|-
! [[15 сентября]] [[2016 год|2016]]
|
Вышел Bash 4.4.
|-
! [[2009 год|2009]] ~ [[2018 год|2018]]
|
Apple отказывается принять четвёртую версию Bash, распространяемую под третьей версией лицензии [[GNU GPL]], и перестаёт поставлять обновления для Bash после версии 3.2 (поставляемой в [[MacOS Mojave]]).
|-
! [[5 июня]] [[2019 год|2019]]
|
Apple объявляет [[zsh]] своей оболочкой по умолчанию<ref>
{{Cite web
| access-date = 2025-08-08
| date        = 2019-06-05
| first      = Armin
| last        = Briegel
| title      = Moving to zsh
| url        = https://scriptingosx.com/2019/06/moving-to-zsh/?form=MG0AV3
| website    = scriptingosx.com
}}
</ref>
и поставляет версию 5.7 в своей [[MacOS Catalina]].<ref>
{{Cite web
| access-date  = 2025-08-08
| archive-date = 2019-12-02
| archive-url  = https://web.archive.org/web/20191202143802/https://support.apple.com/en-us/HT208050
| title        = Apple Support – Use zsh as the default shell on your Mac
| url          = https://support.apple.com/en-us/HT208050
| url-status  = live
| website      = apple.com
}}
</ref><ref>
{{Cite web
| access-date  = 2025-08-08
| archive-date = 2019-06-10
| archive-url  = https://web.archive.org/web/20190610051842/https://www.theverge.com/2019/6/4/18651872/apple-macos-catalina-zsh-bash-shell-replacement-features
| date        = 2019-06-04
| first        = Tom
| last        = Warren
| publisher    = [[The Verge]]
| quote        = The bash binary bundled with macOS has been stuck on version 3.2 for a long time now. Bash v4 was released in 2009 and bash v5 in January 2019. The reason Apple has not switched to these newer versions is that they are licensed with GPL v3. Bash v3 is still GPL v2.
| title        = Apple replaces bash with zsh as the default shell in macOS Catalina
| url          = https://www.theverge.com/2019/6/4/18651872/apple-macos-catalina-zsh-bash-shell-replacement-features
| url-status  = live
| website      = theverge.com
}}
</ref><ref>
{{Cite web
| access-date  = 2025-08-08
| archive-date = 2020-12-31
| archive-url  = https://web.archive.org/web/20201231231721/https://thenextweb.com/dd/2019/06/04/why-does-macos-catalina-use-zsh-instead-of-bash-licensing/
| date        = 2019-06-04
| first        = Matthew
| lang    = en-us
| last        = Hughes
| website      = [[TNW (website)|The Next Web]]
| title        = Why does macOS Catalina use Zsh instead of Bash? Licensing
| url          = https://thenextweb.com/dd/2019/06/04/why-does-macos-catalina-use-zsh-instead-of-bash-licensing/
| url-status  = live
}}
</ref>
|-
! [[7 января]] [[2019 год|2019]]
|
Вышел Bash 5.0.<ref>
{{Cite mailing list
| access-date  = 2025-08-08
| mailing-list = bug-bash
| publisher    = [[GNU Project]]
| title        = Bash-5.0 release available
| url          = https://lists.gnu.org/archive/html/bug-bash/2019-01/msg00063.html
}}
</ref>
|-
! [[7 декабря]] [[2020 год|2020]]
|
Вышел Bash 5.1.<ref>
{{Cite mailing list
| access-date  = 2025-08-08
| mailing-list = bug-bash
| publisher    = [[GNU Project]]
| title        = Bash-5.1 release available
| url          = https://lists.gnu.org/archive/html/bug-bash/2020-12/msg00002.html
}}
</ref>
|-
! [[26 сентября]] [[2022 год|2022]]
|
Вышел Bash 5.2.
|-
! [[2025 год|2025]]
|
Вышел Bash 5.3.
|}
 
== Различия в синтаксисе ==
Подавляющее большинство важных скриптов командного процессора Bourne может выполняться без изменения в bash, за исключением тех, которые ссылаются на специальные переменные Bourne или используют встроенные команды Bourne. Синтаксис команд Bash включает идеи, заимствованные у Korn shell ([[ksh]]) и C shell ([[csh]]), такие как редактирование командной строки, история команд, стек каталогов, переменные <code>$RANDOM</code> и <code>$PPID</code>, синтаксис замены команды <code>$(…)</code>. Когда Bash используется как интерактивный командный процессор, он поддерживает автозавершение имён программ, файлов, переменных и т. п. с помощью клавиши {{Клавиша|Tab}}.
 
== Внутренние команды ==
Интерпретатор bash имеет множество встроенных команд, часть из которых имеет аналогичные исполняемые файлы в [[Операционная система|операционной системе]]. Однако следует обратить внимание, что чаще всего для встроенных команд отсутствуют [[Man|man-страницы]], а при попытке просмотра справки по встроенной команде на самом деле будет выдаваться справка по исполняемому файлу. Исполняемый файл и встроенная команда могут различаться параметрами. Информация по встроенным командам расписана в справочной странице bash:
 
<code>man bash</code>
{| class="wikitable"
!colspan="2"| Ввод-вывод
|-
| <code>[[echo (команда)|echo]]</code> || выводит выражение или содержимое переменной (''stdout''), но имеет ограничения в использовании<ref>Невозможно вывести значение переменной, содержащей <code>-n</code> (в отличие от <code>[[printf]] -- '%s\n' "${переменная}"</code>), так как <code>-n</code> интерпретируется как параметр команды <code>echo</code>.</ref>
|-
| <code>[[printf]]</code> || команда форматированного вывода, расширенный вариант команды <code>echo</code>
|-
| <code>read</code> || «читает» значение переменной со стандартного ввода (''stdin''), в интерактивном режиме это клавиатура
|-
!colspan="2"| Файловая система
|-
| <code>cd</code> || изменяет текущий каталог
|-
| <code>[[pwd]]</code> || выводит название текущего рабочего каталога (от {{lang-en|print working directory}})
|-
| <code>pushd</code> || изменяет текущий каталог с возможностью возврата в обратном порядке
|-
| <code>popd</code> || возвращает текущий каталог после <code>pushd</code>
|-
| <code>dirs</code> || выводит или очищает содержимое стека каталогов, сохранённых через <code>pushd</code>
|-
!colspan="2"| Действия над переменными
|-
| <code>let</code> || производит арифметические операции над переменными
|-
| <code>eval</code> || транслирует список аргументов из списка в команды
|-
| <code>set</code> || изменяет значения внутренних переменных скрипта
|-
| <code>[[unset]]</code> || удаляет переменную
|-
| <code>[[Export (Unix)|export]]</code> || экспортирует переменную, делая её доступной дочерним процессам
|-
| <code>declare</code>, <code>typeset</code> || задают и/или накладывают ограничения на переменные
|-
| <code>getopts</code> || используется для разбора аргументов, передаваемых скрипту из командной строки
|-
!colspan="2"| Управление сценарием
|-
| <code>source</code>, <code>.</code> (точка) || запуск указанного сценария
|-
| <code>[[exit]]</code> || безусловное завершение работы сценария
|-
| <code>exec</code> || заменяет текущий процесс новым, запускаемым командой <code>exec</code>
|-
| <code>shopt</code> || позволяет изменять ключи (опции) оболочки «на лету»
|-
!colspan="2"| Команды
|-
| <code>[[true]]</code> || возвращает код завершения ноль (успешное завершение)
|-
| <code>[[false]]</code> || возвращает код завершения, который свидетельствует о неудаче
|-
| <code>type ''prog''</code> || выводит полный путь к ''prog''
|-
| <code>hash ''prog''</code> || запоминает путь к ''prog''
|-
| <code>help ''COMMAND''</code> || выводит краткую справку по использованию внутренней команды ''COMMAND''
|-
!colspan="2"| Управление запущенными в командной оболочке задачами
|-
| <code>jobs</code> || показывает список запущенных в командной оболочке задач либо информацию о конкретной задаче по её номеру
|-
| <code>fg</code> || переключает поток ввода на текущую задачу (или на определённую задачу, если указан её номер) и продолжает её исполнение
|-
| <code>bg</code> || продолжает исполнение текущей приостановленной задачи (или определённых задач, если указаны их номера) в фоновом режиме
|-
| <code>wait</code> || ожидает завершения указанных задач
|-
|}
 
== Скрипты ==
В простейшем случае [[скрипт]] — простой список команд, записанный в файл. Командный процессор должен знать, что он должен этот файл обработать, а не просто прочесть его содержимое. Для этого служит специальная конструкция, называемая [[shebang]]: <code><nowiki>#!</nowiki></code>. Символ <code><nowiki>#</nowiki></code> задаёт комментарий, но в данном случае shebang означает, что после этого спецсимвола находится путь к интерпретатору для исполнения сценария.
 
=== Синтаксис ===
Синтаксис команд bash — это расширенный синтаксис команд Bourne shell. Окончательная спецификация синтаксиса команд bash есть в Bash Reference Manual, распространяемом проектом [[GNU]].<ref>[http://www.gnu.org/software/bash/manual/bashref.html Bash Reference Manual<!-- Заголовок добавлен ботом -->] {{Wayback|url=http://www.gnu.org/software/bash/manual/bashref.html |date=20190513171205 }}.</ref>
 
==== «Hello world» ====
<source lang="bash">
#!/usr/bin/env bash
echo 'Hello World!'
</source>
 
Этот скрипт содержит только две строки. Первая строка сообщает системе о том, какая программа используется для запуска файла. Вторая строка — это единственное действие, которое выполняется этим скриптом, он собственно печатает «Hello world!» в терминале.


== {{з|(существительное)}} ==
=== Запуск скрипта ===
Для того, чтобы скрипт стал исполняемым, могут быть использованы следующие команды:
<source lang="bash">
chmod +rx scriptname # выдача прав на чтение/исполнение любому пользователю
chmod u+rx scriptname # выдача прав на чтение/исполнение только «владельцу» скрипта
</source>


=== Морфологические и синтаксические свойства ===
Из соображений безопасности путь к текущему каталогу <code>.</code> не включён в переменную окружения <code>$PATH</code>. Поэтому для запуска скрипта необходимо явно указывать путь к текущему каталогу, в котором находится скрипт:
{{сущ en s|bash|e=1}}
<source lang="bash">
./scriptname
</source>


=== Произношение ===
Кроме того, передать такой файл на исполнение [[Интерпретатор командной строки|интерпретатору]] Bash можно и явно, используя команду <code>bash</code>:
{{transcriptions|ˈbæʃ|ˈbæʃɪz||}}


=== Семантические свойства ===
<source lang="bash">
bash scriptname
</source>


==== Значение ====
В этом случае не требуется ни установка прав доступа, ни использование последовательности <code>#!</code> в коде.
# [[удар]] {{пример||перевод=|и=}}
# {{амер.}} [[гулянка]] {{пример||перевод=|и=}}
#


==== Синонимы ====
=== Перенаправление ввода-вывода ===
# —
{{См. также|Стандартные потоки}}
# —
В bash есть встроенные [[Файловый дескриптор|файловые дескрипторы]]: 0 (stdin), 1 (stdout), 2 (stderr).
#
* stdin — стандартный ввод — то, что набирает пользователь в консоли;
* stdout — [[Стандартные потоки|стандартный вывод]] программы;
* stderr — стандартный вывод ошибок.
Для операций с этими и пользовательскими дескрипторами существуют специальные символы: <code>&gt;</code> (перенаправление вывода), <code>&lt;</code> (перенаправление ввода). Символы <code>&amp;</code>, <code>-</code> могут предварять номер дескриптора; например, <code>2>&1</code> — перенаправление дескриптора 2 (stderr) в дескриптор 1 (stdout).


==== Антонимы ====
{| class="wikitable"
#
| <code>0&lt;filename</code> или <code>&lt;filename</code> || Перенаправление ввода из файла <code>filename</code>
# —
|-
#
| <code>1&gt;filename</code> или <code>&gt;filename</code> || Перенаправление вывода в файл «filename». Если отключена опция <code>noclobber</code>, то файл перезаписывается поступающими данными
|-
| <code>1&gt;&#124;filename</code> или <code>&gt;&#124;filename</code> || Перенаправление вывода в файл «filename», файл перезаписывается поступающими данными
|-
| <code>1&gt;&gt;filename</code> или <code> &gt;&gt;filename </code> || Перенаправление вывода в файл «filename», данные добавляются в конец файла. При отсутствии файла он создаётся
|-
| <code>2&gt;filename</code> || Перенаправление стандартного вывода ошибок в файл «filename»
|-
| <code>2&gt;&gt;filename</code> || Перенаправление стандартного вывода ошибок в файл «filename», данные добавляются в конец файла. При отсутствии файла он создаётся
|-
| <code>&amp;&gt;filename</code> || Перенаправление вывода и ошибок в файл «filename»
|-
| <code>2&gt;&amp;1</code> || Перенаправление вывода ошибок на стандартный вывод
|}


==== Гиперонимы ====
Bash имеет индивидуальный синтаксис перенаправления, который не поддерживается в Bourne shell. Пример одновременного перенаправления стандартного вывода и стандартных ошибок:
# —
<source lang="bash">
# —
command &> file
#
</source>
Это проще набрать, чем эквивалентную команду в синтаксисе Bourne shell
<source lang="bash">
command > file 2>&1
</source>


==== Гипонимы ====
=== Перенаправление «из кода скрипта» ===
# —
Поддерживается [[heredoc-синтаксис]]:
# —
* С интерпретацией переменных и конструкций языка внутри блока:
#
<source lang="bash">
$a='многострочный'
command <<MYDOC123
$a
текст
$(<$HOME/my_file.txt)
MYDOC123
</source>
* Без интерпретации переменных:
<source lang="bash">
command <<'PERLCODE'
my $first='Hello';
my $second='world';
say join(', ',$first,$second),'!';
PERLCODE
</source>
* С удалением начальных отступов (поддерживаются только отступы табуляцией):
<source lang="bash">
command <<-'TABSTRIP'
    for ((i=0; i<10; i++))
    do
        echo "$i"
    done
TABSTRIP
</source>


=== Родственные слова ===
Начиная с версии 2.05b, bash может перенаправлять стандартный ввод из строки, используя следующий синтаксис «[[Here-document|here strings]]»:
{{родств-блок
<source lang="bash">
|существительные=
command <<< "string to be read as standard input"
|прилагательные=
</source>
|глаголы=
 
|наречия=
Если строка содержит пробелы, её следует заключить в [[кавычки]] или апострофы, либо экранировать пробелы обратной косой чертой.
|полн=
 
}}
Будьте внимательны: вводимая с использованием [[Here-document|here strings]] строка содержит неявную последовательность завершения строки: либо 1 дополнительный байт [[Перевод строки|line feed]], либо 2 дополнительных байта: [[Возврат каретки|carriage return]] и line feed.
<source lang=bash>
cat -<<<'123' | wc -c
# Результат: 4
cat <(echo -n '123') | wc -c
# Результат: 3
wc -c <<<'123'
# Результат: 4
echo -n 123 | wc -c
# Результат: 3
</source>
 
Начиная с версии 4.1<ref>{{Cite web |url=http://tiswww.case.edu/php/chet/bash/NEWS |title=Bash News |author= |website= |date= |publisher= |access-date=2017-01-18 |archive-date=2017-02-01 |archive-url=https://web.archive.org/web/20170201220832/http://tiswww.case.edu/php/chet/bash/NEWS |url-status=live }}</ref> стало возможным указывать в одной строке терминирующую последовательность символов и, сразу за ней, — скобку. Это может быть полезно для присвоения переменной содержимого here-doc:
<source lang=bash>
var=$( cat -<<'TERMSEQ'
Февраль. Достать чернил и плакать!
Писать о феврале навзрыд,
Пока грохочущая слякоть
Весною чёрною горит.
TERMSEQ)
</source>
При этом BASH будет сгенерировано предупреждающее сообщение.
 
=== Перенаправление для процесса в целом ===
Пример (перенаправление стандартного вывода в файл, запись данных, закрытие файла, сброс stdout):
<source lang="bash">
# make Filedescriptor(FD) 6 a copy of stdout (FD 1)
exec 6>&1
# open file "test.data" for writing
exec 1>test.data
# produce some content
echo "data:data:data"
# close file "test.data"
exec 1>&-
# make stdout a copy of FD 6 (reset stdout)
exec 1>&6
# close FD6
exec 6>&-
</source>
 
Открытие и закрытие файлов:
<source lang="bash">
# open file test.data for reading
exec 6<test.data
# read until end of file
while read -u 6 dta
do
  echo "$dta"
done
# close file test.data
exec 6<&-
</source>
 
=== Подстановка вывода команд ===
Захват вывода внешних команд:
<source lang="bash">
# выполнить 'date' и поместить результат в VAR
VAR="$(date)"
echo "$VAR" #выведет дату на момент вызова предыдущей строки
</source>
 
При этом не поддерживаются строки с нуль-символом, заключительные переводы строк пропадают, в отличие от каналов и прочего файлового [[Ввод-вывод|ввода-вывода]].
 
=== Условный оператор ===
<source lang="bash">
#!/usr/bin/env bash
T1='foo'
T2='bar'
if [[ $T1 == "$T2" ]]
then
  echo 'условие выполняется'
else
  echo 'условие не выполняется'
fi
</source>
Обратите внимание, что кавычки вокруг левой части необязательны.<ref>[http://mywiki.wooledge.org/BashGuide/TestsAndConditionals#Conditional_Blocks_.28if.2C_test_and_.5B.5B.29 BashGuide/TestsAndConditionals] {{Wayback|url=http://mywiki.wooledge.org/BashGuide/TestsAndConditionals#Conditional_Blocks_.28if.2C_test_and_.5B.5B.29 |date=20140212091646 }} — Greg’s Wiki.</ref>
 
=== Циклы ===
<source lang="bash">
#!/usr/bin/env bash
for i in "Номер "{1..10}
do
  echo "$i"
done
</source>
 
<source lang="bash" line="1">
#!/usr/bin/env bash
COUNTER=0
while [[ $COUNTER -lt 10 ]] # До тех пор, пока условие ИСТИННО (возвращает 0) выполнять тело цикла
do
  echo The counter is $COUNTER
  let COUNTER=COUNTER+1
done
</source>
 
<source lang="bash">
#!/usr/bin/env bash
i=0
until [[ $i -eq 10 ]] # До тех пор, пока условие ЛОЖНО (возвращает не 0) выполнять тело цикла
do
  echo "$i"
  i=$(($i+1))
done
</source>
 
<source lang="bash">
#!/usr/bin/env bash
# внутри двойных круглых скобок переменные можно писать в Си-стиле (без $ и разделяя пробелом операторы и операнды)
for (( i = 0; i < 10; i++ ))
do
echo -n "$i; "
done
</source>
 
=== Массивы ===
В bash реализованы только одномерные массивы.
Индексами могут быть как целочисленные значения («обычный» [[Массив (программирование)|массив]]), так и строки ([[ассоциативный массив]], или «хеш»).
 
Несмотря на унификацию синтаксиса для работы с обычными и ассоциативными массивами, первые не являются разновидностью вторых ни с точки зрения конечного пользователя, ни с точки зрения внутренней логики самого интерпретатора.
 
Как естественное следствие поддержки «ассоциативных» ключей, в bash существует крайне ограниченная возможность эмуляции многомерных массивов.
 
==== Общие операции ====
Получить значение элемента как индексированного, так и ассоциативного массива можно:
* По фиксированному значению индекса в линейном массиве или строки в ассоциативном:
<source lang="bash">
declare -a arrLinear=(11 22 33 44)
declare -A arrAssoc=([city]='London' [index]='420224' )
vi=${arrLinear[3]}        # vi=44
va=${arrAssoc['city']}    # va='London'
</source>
* По значению переменной, при этом для индексированных массивов необязательно указывать сигил ($) перед именем переменной, используемой для индесации. Сигил перед переменной индекса обязателен в случае с ассоциативными массивами:
<source lang="bash">
declare -i n=3
vi=${arrLinear[$i]}      # vi=44
vi=${arrLinear[i]}      # аналогично предыдущему, но без сигила
 
declare index='city'
va=${arrAssoc[$index]}  # va='London', и это правильно
va=${arrAssoc[index]}    # va='420224', и это ошибочный результат, если подразумевалось [$index]
va=${arrAssoc['index']}  # va='420224'
</source>
 
Получить строку, состоящую из всех<ref name="массивы с пробелами">Для получения действительно всех элементов, включая элементы из пробелов и пустые строки, обязательно использовать кавычки.</ref> элементов массива, разделённых пробелом.
<source lang="bash">
values="${arr[@]}"
</source>
 
Получить строку со всеми<ref name="массивы с пробелами"/> индексами или ключами массива, независимо от того, численные они или текстовые:
<source lang="bash">
keys="${!arr[@]}"
</source>
 
Осуществить массовую замену первого вхождения подстроки «MAY» на «MARCH» во всех<ref name="массивы с пробелами"/> элементах массива и вернуть строку, составленную из результирующих элементов массива, разделённых пробелом:
<source lang="bash">
values="${arr[@]/MAY/MARCH}"
</source>
То же самое, но в каждом<ref name="массивы с пробелами"/> элементе массива будут заменены все вхождения подстроки «MAY»:
<source lang="bash">
values="${arr[@]//MAY/MARCH}"
</source>
 
До сих пор не все заявленные в документации возможности правильно работают для массивов. Например: <source lang="bash">[ -v 'имя_массива' ]</source> неправильно срабатывает для пустого массива.<ref>Здесь апострофы употреблены правильно.</ref>
 
==== Операции с индексированными массивами ====
Bash имеет поддержку одномерных массивов. Инициализировать элементы массива можно в виде: <code>my_array[xx]</code>. Также можно явно объявить массив в сценарии, с помощью директивы <code>declare</code>:
<source lang="bash">
declare -a my_array
</source>
Обращаться к отдельным элементам массива можно с помощью фигурных скобок: <code>"${my_array[xx]}"</code>.
 
Инициализировать индексированный массив можно двумя способами:
 
1)
<source lang="bash">
Array=(element1 element2 element3)
</source>
2)
<source lang="bash">
temp_array[0]=element1
temp_array[5]=element
temp_array[9]=elementN
</source>
 
Добавление элементов в конец индексированного массива:
<source lang="bash">
declare -a arrAnimals
arrAnimals=(dog elephant horse cow fox koala turtle)
# Выводим содержимое массива:
echo "${arrAnimals[@]}"
# В конец массива arrAnimals добавляем новый элемент: "pig"
arrAnimals+=(pig)
# И снова показываем содержимое массива:
echo "${arrAnimals[@]}"
</source>
 
Получить первый элемент массива:
<source lang="bash">
echo "${arrAnimals[0]}"
</source>
 
Как индексированные, так и ассоциативные массивы поддерживают так называемые «срезы»:
<source lang="bash">
# Ещё один способ получить первый элемент массива
echo "${arrAnimals[@]:0:1}"
 
# Вывести 3 элемента массива, начиная со 2-го:
echo "${arrAnimals[@]:2:3}"
</source>
Примечание: в случае с ассоциативными массивами порядок следования значений в общем случае будет случайным (определяется используемой хеш-функцией), поэтому операция среза на ассоциативном массиве хотя и допустима, но имеет крайне ограниченную область практического применения.
 
В массивах с числовыми индексами допустима «обратная» («негативная») адресация, позволяющая получить доступ к элементам, начиная с конца массива:
<source lang="bash">
# Значение последнего элемента массива
echo "${arrAnimals[-1]}"
# Значение предпоследнего элемента массива
echo "${arrAnimals[-2]}"
# ... и т.д.
</source>
 
С помощью встроенной команды <code>mapfile</code> (синоним: <code>readarray</code>) можно отображать содержимое текстового файла в индексированный массив:
<source lang="bash">
declare -a fileWithLogins
mapfile fileWithLogins </etc/passwd
for ((i=0; i<${#fileWithLogins[@]}; i++))
do
echo "Line #$i: ${fileWithLogins[$i]}"
done
</source>
 
==== Операции с ассоциативными массивами ====
Начиная с версии 4.0 в bash появилась поддержка ассоциативных массивов (так называемых hash-массивов).
 
Для объявления ассоциативных массивов используется ключ <code>-A</code> встроенной команды <code>declare</code>:
<source lang="bash">
declare -A hshArray
</source>
 
Как и в случае с индексированными массивами, для заполнения ассоциативных массивов могут использоваться два различных синтаксиса:
 
1)
<source lang="bash">
TheCapitalOf[Georgia]='Tbilisi'
TheCapitalOf[Australia]='Canberra'
TheCapitalOf[Pakistan]='Islamabad'
</source>
2)
<source lang="bash">
TheCapitalOf=([Georgia]='Tbilisi' [Australia]='Canberra' [Pakistan]='Islamabad')
</source>
 
С помощью ассоциативных массивов можно имитировать поддержку многомерных массивов:
<source lang="bash">
declare -A a # объявляет ассоциативный массив 'a'
i=1; j=2 # инициализация нескольких индексов
a[$i,$j]=5 # присвоение значения "5" в ячейку "$i,$j" (т.е. "1,2")
echo ${a[$i,$j]} # вывод хранимых значений из "$i,$j"
</source>
 
К сожалению, в текущих версиях bash скопировать содержимое одного ассоциативного массива в другой простым присваиванием невозможно.
Данную проблему можно только обойти, для чего существуют два принципиально разных подхода:
 
1) Эмулировать объявление второго хеша «с нуля» путём копирования объявления первого хеша:
<source lang="bash">
declare -A hsh1
hsh1=(...)
 
source <(declare -p hsh1 | sed 's/^declare -A hsh1/declare -A hsh2/')
</source>
 
2) Перебрать все<ref name="массивы с пробелами"/> элементы хеша-источника и скопировать их в целевой хеш:
<source lang="bash">
declare -A hsh1 hsh2
hsh1=(...)
 
for k in "${!hsh1[@]}"
do
hsh2["$k"]="${hsh1["$k"]}"
done
</source>
 
==== Безопасная работа с массивами ====
Массивы являются удобным способом передачи динамически сгенерированных аргументов в функции или команды. При этом каждый элемент массива представляет собой отдельный аргумент.
<syntaxhighlight lang="bash">
args=( ls -l -a / )
ls "${args[@]}" # ls -l -a /
ls ${args[@]} # ls -l -a /
ls ${args[*]} # ls -l -a /
</syntaxhighlight>
Однако при подобном использовании массивов следует быть осторожным ввиду особенностей раскрытия массивов при использовании в качестве индексов специальных символов <code>@</code> и <code>*</code>.
 
Если массив заключён в кавычки и раскрывается с помощью индекса <code>@</code>, то образуется строка из слов, где каждое слово — отдельный элемент массива. Однако если не заключить раскрытие массива в двойные кавычки, то может получиться совсем другой результат: пробелы, входящие в состав элементов массива, становятся разделителями слов.<syntaxhighlight lang="bash">
args=( -l -a '/home/user/Рабочий стол' )
ls "${args[@]}" # просмотр содержимого каталога '/home/user/Рабочий стол'
ls ${args[@]} # ошибка: каталогов '/home/user/Рабочий' и './стол' не существует
</syntaxhighlight>
Массив с индексом <code>*</code>, заключённый в двойные кавычки, раскрывается в одну строку, соединяя все элементы массива через разделители, хранимые в переменной <code>IFS</code>. Если не указать двойные кавычки, то массив раскрывается аналогично раскрытию при использовании индекса <code>@</code>.
<syntaxhighlight lang="bash">
args=( '' usr local bin )
IFS='/' ls "${args[*]}" # просмотр содержимого каталога '/usr/local/bin'
IFS='/' ls ${args[*]} # поочерёдный просмотр содержимого каталогов '.', './usr', './local' и './bin'
</syntaxhighlight>
При создании массива из содержимого текстовой переменной необходимо учитывать возможное наличие пробелов в тексте. Например, в качестве одного из способов создания массива из строки с перечислением можно рассматривать замену символа-разделителя на пробел. Однако наличие пробелов в разделяемых элементах приведёт к дроблению самих элементов на части.
<syntaxhighlight lang="bash">
array=( ${text//,/} ) # неправильно: текст в переменной 'text' мог содержать пробельные символы
 
IFS=',' array=( $text ) # правильно: раздельтельным символом является запятая.
IFS=',' read -r -a array <<< "$text" # правильно (альтернативный вариант с перенаправлением содержимого переменной 'text' в команду 'read')
</syntaxhighlight>
К ошибкам может привести создание массива из текста, полученного в качестве вывода команд или из файла, так как не только переводы строк, но также и пробелы с символами [[Табуляция|табуляции]] по умолчанию будут считаться разделителями<ref>{{Cite web |url=https://linux.die.net/man/1/bash |title=bash(1): GNU Bourne-Again SHell — Linux man page |publisher=linux.die.net |lang=en |access-date=2017-07-11 |archive-date=2019-12-27 |archive-url=https://web.archive.org/web/20191227012646/https://linux.die.net/man/1/bash |url-status=live }}</ref>.
<syntaxhighlight lang="bash">
array=( "$(ls)" ) # неправильно: пробелы в названии файлов могут разбить имя файла на два элемента массива
 
IFS=$'\n' array=( "$(ls)" ) # правильно: разделителем будет только перевод строк
mapfile -t array < <(ls) # правильно: альтернативный вариант через встроенную команду mapfile
</syntaxhighlight>
 
=== Конвейер ===
[[Конвейер (Unix)|Конвейер]] передаёт вывод предыдущей команды на ввод следующей или на вход командного интерпретатора. Метод часто используется для связывания последовательности команд в единую цепочку. Конвейер обозначается символом [[Вертикальная черта|вертикальной черты]] <code>|</code>.
 
Пример ([[grep]] работает как фильтр для стандартного вывода):
<source lang="bash">
cat filename | grep pattern
</source>
 
=== Логические операции ===
Логическое ИЛИ обозначается как <code>||</code>. В операциях проверки условий оператор <code>||</code> возвращает 0 (success), если один из операндов имеет значение true (ИСТИНА).
 
Логическое И обозначается как <code>&amp;&amp;</code>. В операциях проверки условий оператор <code>&&</code> возвращает 0 (success) тогда и только тогда, когда оба операнда имеют значение true (ИСТИНА).
 
Примечание: Возможная путаница в понимании возникает из-за того, что ''команда'' <code>true</code> (и успешное завершение любой команды) завершается с ''кодом возврата'' 0, success (<code>false</code>, наоборот, не 0), в то время как ''логическое значение'' true/false — отлично от нуля/равно нулю.
 
Примеры:
<source lang="bash">
if false; then echo "successfully"; else echo "unsuccessfully"; fi
unsuccessfully
</source>
 
<source lang="bash">
let "a=(( 1 && 0 && 123))"; echo $?; echo $a
1 # Код завершения команды (нулевой результат вычисления арифметического выражения)
0 # Значение переменной "a", результат логической операции
if (( 1 && 0 && 123)); then echo "true"; else echo "false"; fi
false
 
let "a=(( 1 && 123 && -345 ))"; echo $?; echo $a
0 # Код завершения команды
1 # Значение переменной "a", результат логической операции
if (( 1 && 123 && -345 )); then echo "true"; else echo "false"; fi
true
</source>
 
<source lang="bash">
false && echo "Успешное завершение" || echo "Неуспешное завершение"
Неуспешное завершение
</source>
 
=== Целочисленная математика ===
Bash может выполнять целочисленные вычисления внутри процесса, используя команду <code>((…))</code> и синтаксис переменной <code>$((…))</code><ref>Устаревший вариант: <code>$[…]</code>.</ref>, как показано ниже:
<source lang="bash">
VAR=55 # Устанавливаем переменную VAR, равной 55
((VAR = VAR + 1)) # Добавляем единицу к переменной VAR. Обратите внимание на отсутствие знака '$'
((VAR+=1)) # Сокращённая форма записи инкремента
((++VAR)) # Другой способ увеличения VAR на единицу. Выполняет префиксный инкремент
((VAR++)) # Другой способ увеличения VAR на единицу. Выполняет постфиксный инкремент
echo $((VAR * 22)) # Умножаем VAR на 22 и передаем результат команде
echo $[VAR * 22] # Устаревший способ сделать то же
((VAR<<3)) # Побитовый сдвиг влево (то же, что VAR*8)
((VAR>>3)) # Побитовый сдвиг вправо (то же, что VAR/8)
</source>
 
Команда <code>((…))</code> также может использоваться в условных утверждениях, так как её исходный параметр — это 0 или 1, которые могут интерпретироваться как true или false:
<source lang="bash">
if ((VAR == Y * 3 + X * 2))
then
  echo Yes
fi
((Z > 23)) && echo Yes
</source>
 
Команда <code>((…))</code> поддерживает следующие операторы сравнения: <code>==</code> <code>!=</code> <code>&gt;</code> <code>&lt;</code> <code>&gt;=</code> <code>&lt;=</code>.
 
Bash не поддерживает вычисления внутри процесса с числами с плавающей точкой. Только командные процессоры [[Unix]] [[Korn shell]] (версия [[1993 год]]а) и [[zsh]] (начиная с версии 4.0) поддерживают эту возможность.
 
Список математических операций: <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>, <code>**</code> (возведение в степень), <code>%</code> (деление по модулю, остаток от деления), <code>let</code> — позволяет использовать сокращения арифметических команд (сокращая количество используемых переменных; например: <code>a += b</code> эквивалентно <code>a = a + b</code> и т. п.).
 
== Переменные и аргументы ==
Аргументы:
{| class="wikitable"
| <code>$$</code> || pid текущего shell (самого процесса-сценария)
|-
| <code>$!</code> || pid последнего процесса в фоновом режиме
|-
| <code>$?</code> || код возврата последнего процесса (функции или скрипта)
|-
| <code>$''x''</code> || где ''x'' — номер параметра, переданного скрипту (<code>$1</code>, <code>$2</code> и т. д., <code>$0</code> — последний запущенный скрипт)
|-
| <code>$#</code> || количество аргументов командной строки
|-
| <code>$*</code> || все<ref name="массивы с пробелами"/> аргументы в виде одной строки (слова)
|-
| <code>$@</code> || то же самое, что и <code>$*</code>, но при этом каждый<ref name="массивы с пробелами"/> параметр представлен как отдельная строка (слово)
|-
| <code>$-</code> || список флагов, переданных сценарию
|-
| <code>$_</code> || содержит последний аргумент предыдущей команды
|}
 
Встроенные переменные:
{| class="wikitable"
| <code>$BASH</code> || путь к исполняемому файлу bash
|-
| <code>$BASHPID</code> || PID текущего bash * (см. Примечание)
|-
| <code>$BASH_VERSINFO[n]</code> || массив, состоящий из 6 элементов, содержащий информацию о версии bash
|-
| <code>$BASH_VERSION</code> || версия Bash, установленного в системе
|-
| <code>$DIRSTACK</code> || содержимое вершины стека каталогов
|-
| <code>$EDITOR</code> || заданный по умолчанию редактор
|-
| <code>$EUID</code> || «эффективный» идентификационный номер пользователя (Effective User ID)
|-
| <code>$FUNCNAME</code> || имя текущей функции
|-
| <code>$GLOBIGNORE</code> || перечень шаблонных символов, которые будут проигнорированы при выполнении подстановки имён файлов (globbing)
|-
| <code>$GROUPS</code> || группы, к которым принадлежит текущий пользователь
|-
| <code>$HOME</code> || домашний каталог пользователя
|-
| <code>$HOSTNAME</code> || сетевое имя хоста
|-
| <code>$HOSTTYPE</code> || тип машины (идентифицирует аппаратную архитектуру)
|-
| <code>$IFS</code> || разделитель полей во вводимой строке
|-
| <code>$LC_COLLATE</code> || задаёт порядок сортировки символов, в операциях подстановки имён файлов и в поиске по шаблону
|-
| <code>$LC_CTYPE</code> || определяет кодировку символов
|-
| <code>$LINENO</code> || Номер строки исполняемого сценария
|-
| <code>$MACHTYPE</code> || аппаратная архитектура
|-
| <code>$OLDPWD</code> || прежний рабочий каталог
|-
| <code>$OSTYPE</code> || тип операционной системы
|-
| <code>$PATH</code> || путь поиска (включает в себя каталоги <code>/usr/bin/</code>, <code>/usr/X11R6/bin/</code>, <code>/usr/local/bin</code> и т. д.)
|-
| <code>$PIPESTATUS</code> || Код возврата канала (конвейера)
|-
| <code>$PPID</code> || PID (идентификатор) родительского процесса
|-
| <code>$PS1</code> || приглашение командной строки
|-
| <code>$PS2</code> || вторичное приглашение командной строки, выводится тогда, когда от пользователя ожидается дополнительный ввод. Обычно отображается как «>»
|-
| <code>$PS3</code> || третичное приглашение, выводится, когда пользователь должен сделать выбор в операторе <code>select</code>
|-
| <code>$PS4</code> || приглашение четвёртого уровня, выводится (в изменённом виде) в начале каждой строки отладочного вывода тогда, когда сценарий вызывается с ключом <code>-x</code>. Обычно отображается как «+», «++» и т. д.
|-
| <code>$PWD</code> || рабочий (текущий) каталог
|-
| <code>$REPLY</code> || переменная по умолчанию, куда записывается ввод пользователя, выполненный с помощью команды <code>read</code>
|-
| <code>$SECONDS</code> || время работы сценария (в секундах)
|-
| <code>$SHELLOPTS</code> || список допустимых опций интерпретатора (доступна только для чтения)
|-
| <code>$SHLVL</code> || уровень вложенности shell
|}
* Примечание: отличается от $$ при определенных обстоятельствах, таких как подоболочки, которые не требуют повторной инициализации bash.
Пример:
<pre>$ echo $(echo $BASHPID $$)      $$      $BASHPID
              25680    16920    16920    16920
#            |        |        |        |
#            |        |        |        -- $BASHPID outside of the subshell
#            |        |        -- $$ outside of the subshell
#            |        -- $$ inside of the subshell
#            -- $BASHPID inside of the subshell
</pre>


=== Этимология ===
Происходит от {{этимология:|en}}


=== Фразеологизмы и устойчивые сочетания ===
=== Регулярные выражения внутри процесса ===
*
Bash 3.0 поддерживает встроенные [[регулярные выражения]] с синтаксисом, подобным синтаксису [[Perl]]:
<source lang="bash">
[[string =~ regex]]
</source>
Синтаксис регулярных выражений задокументирован на страницах документации man 7 regex. Статус выхода устанавливается в 0, если регулярное выражение совпало со строкой, и 1, если нет. Значение подвыражения, заключённого в скобки, можно получить<ref name="массивы с пробелами"/> через переменную <code>${BASH_REMATCH[@]}</code>, например:
<source lang="bash">
REGEXP='foo(bar)bl(.*)'
if [["abcfoobarbletch" =~ $REGEXP]]
then
  echo "Регулярное выражение совпало со строкой!"
  echo "$BASH_REMATCH"      # выводит: foobarbletch
  echo "${BASH_REMATCH[1]}" # выводит: bar
  echo "${BASH_REMATCH[2]}" # выводит: etch
fi
</source>


=== Библиография ===
Встроенные регулярные выражения обычно работают быстрее, чем выполнение внешней команды grep, потому что соответствующее регулярное выражение выполняется в рамках процесса bash. Если регулярное выражение или строка содержат пробелы или метасимволы (такие как <code>*</code> или <code>?</code>), их следует взять в кавычки. Рекомендуется использовать переменную для хранения регулярного выражения, как в вышеприведённом примере, для избежания проблем с экранированием специальных символов. Можно использовать вывод bash с опцией <code>-x</code> для проверки, как именно bash воспринимает ваше регулярное выражение.
*  


<!-- Служебное: -->
== Расширение скобок ==
{{improve|en|морфо|пример|этимология}}
Возможность расширения скобок заимствована у [[csh]]. Она позволяет произвольной строке быть сформированной с использованием похожей техники, как это делается с названиями файлов. Однако в bash сгенерированные строки не обязаны быть именами файлов. Результат каждого расширения строки не сортируется, сохраняется порядок слева направо:
{{Категория|язык=en|||}}
<source lang="bash">
# Это особенность присущая bash
echo a{p,c,d,b}e # ape ace ade abe
</source>


== {{з|(глагол)}} ==
Не следует использовать эту особенность, если скрипт планируется портировать, потому что в традиционных скриптах расширение строки не будет действовать:
<source lang="bash">
# Традиционная оболочка не даёт тот же результат
echo a{p,c,d,b}e # a{p,c,d,b}e
</source>


=== Морфологические и синтаксические свойства ===
Когда используется расширение скобок в сочетании с символами подстановки, скобки раскрываются первыми, а затем результат обрабатывается в обычном режиме. Таким образом, список JPEG- и PNG-изображений в текущем каталоге может быть получен так:
{{гл en reg e|bash}}
<source lang="bash">
ls *.{jpg,jpeg,png} # скобки раскрываются до *.jpg *.jpeg *.png, после чего выполняется поиск по маскам
</source>


=== Произношение ===
== Горячие клавиши ==
{{transcription|ˈbæʃ}}
* {{Клавиша|tab}}: [[Автодополнение]] строки за курсором.
* {{Клавиша|Ctrl|!}} {{Клавиша|Ctrl|!}}: Повторить последнюю команду.
* {{Клавиша|Ctrl|a}}: Перемещает [[курсор]] в начало строки (эквивалентно клавише {{Клавиша|Home}}).
* {{Клавиша|Ctrl|b}}: Перемещает курсор на один символ назад (эквивалентно клавише {{Клавиша|←}}).
* {{Клавиша|Ctrl|r}}: Поиск по набранным ранее командам.
* {{Клавиша|Ctrl|c}}: Посылает сигнал [[SIGINT]] текущему заданию, который обычно (но не всегда) прекращает и закрывает его.
* {{Клавиша|Ctrl|d}}: Посылает маркер [[EOF]], который (если не отключено опцией и текущая строка не содержит текста) закрывает текущую [[Оболочка операционной системы|оболочку]] (эквивалентно команде [[exit]]), при вводе в исполняющуюся программу завершает ввод, если в строке нет текста, иначе завершает строку без символа завершения строки.
* {{Клавиша|Ctrl|d}}: Удаляет текущий символ (только если есть текст на текущей строке) (эквивалентно клавише {{Клавиша|Delete}}).
* {{Клавиша|Ctrl|e}}: Перемещает курсор в конец строки (эквивалентно клавише {{Клавиша|End}}).
* {{Клавиша|Ctrl|f}}: Перемещает курсор на один символ вперёд (эквивалентно клавише {{Клавиша|→}}).
* {{Клавиша|Ctrl|h}}: Удаляет предыдущий символ (то же самое, что и клавиша {{Клавиша|Backspace}}).
* {{Клавиша|Ctrl|i}}: Эквивалентно клавише {{Клавиша|Tab}}.
* {{Клавиша|Ctrl|j}}: Эквивалентно клавише {{Клавиша|Enter}}.
* {{Клавиша|Ctrl|k}}: Очищает содержимое строки после курсора и копирует это в [[буфер обмена]] экземпляра bash (kill ring).
* {{Клавиша|Ctrl|l}}: Очищает содержимое экрана (эквивалентно команде <code>clear</code>).
* {{Клавиша|Ctrl|m}}: Эквивалентно клавише {{Клавиша|Enter}}.
* {{Клавиша|Ctrl|n}}: (следующее) перелистывает к следующей команде (эквивалентно клавише {{Клавиша|↓}}).
* {{Клавиша|Ctrl|o}}: Выполняет найденную команду в истории, и выбирает следующую строку относительно текущей строки в истории для того, чтобы отредактировать.
* {{Клавиша|Ctrl|p}}: (предыдущее) перелистывает к предшествующей команде (эквивалентно клавише {{Клавиша|↑}}).
* {{Клавиша|Ctrl|q}}: Возобновить вывод процесса.
* {{Клавиша|Ctrl|s}}: Приостановить вывод процесса (stop).
* {{Клавиша|Ctrl|t}}: Обмен местами соседних символов.
* {{Клавиша|Ctrl|u}}: Очищает содержание строки до курсора и копирует его в [[буфер обмена]] экземпляра bash (kill ring).
* {{Клавиша|Ctrl|w}}: Убирает слово до курсора и копирует его в [[буфер обмена]] экземпляра bash (kill ring).
* {{Клавиша|Ctrl|y}}: добавляет содержимое [[Буфер обмена|буфера обмена]] экземпляра bash от позиции курсора.
* {{Клавиша|Ctrl|z}}: Посылает сигнал [[SIGTSTP]] текущему заданию, который приостанавливает его выполнение, и возобновляет приём команд. Для возобновления его выполнения в фоновом режиме можно ввести команду bg. Для того, чтобы вернуть его из фонового режима или приостановки, можно выполнить fg.
* {{Клавиша|Ctrl|/}}: Прервать текущий процесс с дампом памяти (core dump), послав ему сигнал.
* {{Клавиша|Ctrl|_}} ({{Клавиша|Ctrl|Shift|-}}): Откат редактирования.
* {{Клавиша|Alt|>}}: переход к последней команде в истории.
* {{Клавиша|Alt|b}}: (назад) перемещает курсор назад на одно слово (эквивалентно клавише {{Клавиша|Ctrl|←}}).
* {{Клавиша|Alt|d}}: Сокращает слово после курсора.
* {{Клавиша|Alt|f}}: (вперёд) перемещает курсор вперёд на одно слово (эквивалентно клавише {{Клавиша|Ctrl|→}}).
* {{Клавиша|Alt|t}}: Меняет два слова перед курсором местами.
* {{Клавиша|Alt|.}}: Добавляет последний аргумент предыдущей команды.
* {{Клавиша|Alt|c}}: Заменить букву под курсором на заглавную.
* {{Клавиша|Alt|l}}: Заменить букву под курсором на строчную.
* {{Клавиша|Ctrl|x}} {{Клавиша|Ctrl|x}}: Переносит курсор к началу строки от текущей позиции, и обратно.
* {{Клавиша|Ctrl|x}} {{Клавиша|Ctrl|e}}: Редактирует текущую строку в программе $EDITOR, или vi, если не предопределено.
* {{Клавиша|Ctrl|x}} {{Клавиша|Ctrl|v}}: Вывод на экран информации о версии текущего экземпляра bash.


=== Семантические свойства ===
== Стартовые скрипты ==
Bash при запуске вызывает команды из множества различных скриптов.


==== Значение ====
Когда bash вызывается как [[Интерактивность|интерактивная]] [[Оболочка операционной системы|оболочка]] входа в систему, первым делом он читает и вызывает команды из файла <code>/etc/profile</code>, если этот файл существует. После чтения этого файла он смотрит следующие файлы в следующем порядке: <code>~/.bash_profile</code>, <code>~/.bash_login</code> и <code>~/.profile</code>, читает и вызывает команды из первого, который существует и доступен для чтения. При выходе bash читает и выполняет команды из файла <code>~/.bash_logout</code>.
# [[ударить]], [[трахнуть]] {{пример||перевод=|и=}}
# резко [[критиковать]] {{пример||перевод=|и=}}
#


=== Синонимы ===
Когда запускается интерактивная оболочка, но не для входа в систему, bash читает и исполняет команды из файлов <code>/etc/bash.bashrc</code> и <code>~/.bashrc</code>, если они существуют. Это может быть отменено опцией <code>-norc</code>. Опция <code>-rcfile file</code> заставит bash использовать команды из файла <code>file</code> вместо <code>/etc/bash.bashrc</code> и <code>~/.bashrc</code>.
#
#
#


==== Антонимы ====
== Переносимость ==
#
Первой строкой скрипта должна быть запись <code>#!/bin/bash</code>, если известен абсолютный путь к исполняемому файлу, либо <code>#!/usr/bin/env bash</code> для автоматического определения пути к исполняемому файлу через команду [[env]] с помощью переменной окружения [[PATH (переменная)|PATH]]<ref>{{Cite web|url=http://man7.org/linux/man-pages/man1/env.1.html|title=env(1) — Linux manual page|publisher=man7.org|access-date=2017-01-21|archive-date=2017-01-13|archive-url=https://web.archive.org/web/20170113193813/http://man7.org/linux/man-pages/man1/env.1.html|url-status=live}}</ref>.
#
#


==== Гиперонимы ====
Скрипты оболочек, написанные со специфическими для bash особенностями, не будут работать на системах, где используется [[Bourne shell|Bourne shell (sh)]] или один из его аналогов, если bash не был установлен в качестве дополнительной оболочки. Эта проблема стала особенно важной, когда [[Ubuntu]] начал с октября [[2006 год]]а поставлять [[Debian Almquist shell]] (dash) как скриптовую оболочку по умолчанию, что привело к неработоспособности многочисленных скриптов.
#
#
#


==== Гипонимы ====
== Графический интерфейс к скриптам ==
#
Существует множество программ, позволяющих создавать [[Графический интерфейс пользователя|графический интерфейс]] к bash-скриптам.
#
* [[dialog]] — утилита, позволяющая создавать диалоговые окна в консоли, использует библиотеки [[curses]] и [[ncurses]].
#
* [[whiptail]] — аналог утилиты dialog, использует библиотеку [[newt]].
* [[zenity]] — наиболее популярное приложение для создания графического интерфейса к скриптам.
* [[kdialog]] — аналог zenity в среде [[KDE]].
* [[yad]] — форк zenity, с большими возможностями.
* [[xdialog]] — замена dialog, предназначенная для придания запускаемым из терминала программам интерфейса [[X Window System]].
* [[gtkdialog]] — наиболее функциональная утилита для создания [[Графический интерфейс пользователя|графических]] приложений на bash-скриптах.


=== Родственные слова ===
== См. также ==
{{родств-блок
* [[GNU Readline]]
|существительные=bashment, bashing
|прилагательные=
|глаголы=
|наречия=
|полн=
}}


=== Этимология ===
== Примечания ==
Впервые в 1641 г., вероятно, либо скандинавского происхождения (ср. шв. [[basa]], дат. [[baske]]), от др.-норск [[*basca]] ([[бить]]), либо же звукоподражание.
{{примечания}}


=== Фразеологизмы и устойчивые сочетания ===
== Ссылки ==
*
* {{cite web|url=https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html|title=Bash Reference Manual|lang=en|description=Официальное руководство|access-date=2010-11-22|archive-url=https://www.webcitation.org/618xRKJBw?url=http://www.gnu.org/software/bash/manual/bashref.html|archive-date=2011-08-23|url-status=dead}}
* {{cite web
|url        = http://citforum.ru/operating_systems/manpages/bash/index.shtml
|title        = Bash Reference Manual
|description        = Перевод [[man]]-страницы от 2004 года
|access-date        =
|url-status        = dead
|archive-date        = 2012-04-23
|archive-url        = https://web.archive.org/web/20120423061220/http://citforum.ru/operating_systems/manpages/bash/index.shtml
}}
* {{cite web
|url          = http://rus-linux.net/MyLDP/BOOKS/abs-guide/flat/abs-book.html
|title        = Advanced Bash-Scripting Guide
|description  = Расширенное руководство по написанию bash-скриптов
|lang        = ru
|access-date  = 2011-08-06
|url-status      = dead
|archive-date = 2011-08-28
|archive-url  = https://web.archive.org/web/20110828024300/http://rus-linux.net/MyLDP/BOOKS/abs-guide/flat/abs-book.html
}}
* {{cite web
|url        = http://bappoy.pp.ru/tag/bash-pitfalls
|title      = Частые ошибки программирования на Bash
|access-date  = 2010-11-22
|archive-url  = https://www.webcitation.org/618xPFpAF?url=http://bappoy.pp.ru/tag/bash-pitfalls
|archive-date = 2011-08-23
|url-status    = dead
}}
* {{cite web
|url        = http://ruslandh.narod.ru/howto_ru/Bash-Prog-Intro/Bash-Prog-Intro.html
|title        = Введение в программирование на bash
|access-date        = 2010-11-22
|url-status        = dead
|archive-date        = 2011-08-27
|archive-url        = https://web.archive.org/web/20110827233426/http://ruslandh.narod.ru/howto_ru/Bash-Prog-Intro/Bash-Prog-Intro.html
}}
* {{cite web
|url        = http://ru.opensuse.org/Bash
|title      = Bash
|publisher  = openSuse wiki
|lang        = ru
|access-date  = 2010-11-22
|archive-url  = https://www.webcitation.org/618xQ1ft3?url=http://ru.opensuse.org/Bash
|archive-date = 2011-08-23
|url-status    = dead
}}
* {{cite web
|url        = http://www.ss64.com/bash/
|title      = Описание команд bash
|lang        = en
|access-date  = 2010-11-22
|archive-url  = https://www.webcitation.org/618xQrWNK?url=http://ss64.com/bash/
|archive-date = 2011-08-23
|url-status    = dead
}}
* {{cite web
|url        = http://www.ibm.com/developerworks/ru/library/l-bash-parameters/index.html?ca=dre-ru
|title      = Полезные советы Linux: Параметры bash и расширения параметров
|author      = Ян Шилдс (Ian Shields)
|lang        = ru
|archive-url  = https://www.webcitation.org/6BQdrirVt?url=http://www.ibm.com/developerworks/ru/library/l-bash-parameters/index.html?ca=dre-ru
|archive-date = 2012-10-15
|url-status    = dead
}}


=== Библиография ===
{{Команды Unix}}
*
{{Интерфейсы пользователя в Unix-подобных системах}}
{{GNU}}
{{POSIX.1-2008}}


<!-- Служебное: -->
[[Категория:Командные оболочки Unix]]
{{improve|en|морфо|пример|семантика?}}
[[Категория:Программное обеспечение проекта GNU]]
{{Категория|язык=en|Глаголы критики||}}
[[Категория:Скриптовые языки]]
{{длина слова|4|en}}
[[Категория:Свободное программное обеспечение, написанное на Си]]
[[Категория:Свободное кроссплатформенное программное обеспечение]]

Текущая версия от 22:20, 30 марта 2026

Ошибка скрипта: Модуля «hatnote» не существует.{{#if: | }} Шаблон:КарточкаШаблон:Сортировка: по изображениям{{#if:||Шаблон:Категория по дате}}Ошибка скрипта: Модуля «check for unknown parameters» не существует.Шаблон:ИТ:Общие проверки Bash (от англ. Шаблон:Lang-en2, каламбур Шаблон:Lang-en2 — «возрождённый» shell) — усовершенствованная и модернизированная вариация командной оболочки Bourne shell. Одна из наиболее популярных современных разновидностей командной оболочки UNIX. Особенно популярна в среде Linux, где она часто используется в качестве предустановленной командной оболочки.

Представляет собой командный процессор, работающий, как правило, в интерактивном режиме в текстовом окне. Bash также может читать команды из файла, который называется скриптом (или сценарием). Как и все Unix-оболочки, он поддерживает автодополнение имён файлов и каталогов, подстановку вывода результата команд, переменные, контроль над порядком выполнения, операторы ветвления и цикла. Ключевые слова, синтаксис и другие основные особенности языка были заимствованы из sh. Другие функции, например, история, были скопированы из csh и ksh. Bash в основном соответствует стандарту POSIX, но с рядом расширений<ref>Шаблон:Cite web</ref>.

Название «bash» является акронимом от англ. Шаблон:Lang-en2 («ещё-одна-командная-оболочка-Борна») и представляет собой игру слов: Bourne-shell — одна из популярных разновидностей командной оболочки для UNIX (sh), автором которой является Стивен Борн (1978), усовершенствована в 1987 году Брайаном Фоксом. Фамилия Bourne (Борн) перекликается с английским словом Шаблон:Lang-en2, означающим «родившийся», отсюда: рождённая-вновь-командная оболочка.

В сентябре 2014 года в bash была обнаружена широко эксплуатируемая уязвимость Bashdoor.

История

Функциональность сценариев оболочки изначально появилась в файлах, называемых «runcom» в честь появившегося в 1963 году макропроцессора с тем же названием. Суффикс «rc» — это сокращение от «runcom».<ref> Шаблон:Cite web</ref> Термин «оболочка» был придуман Луи Пузеном в 1964 или 1965 году и появился в его статье 1965 года «Оболочка, глобальный инструмент для вызова и цепочки процедур в системе», в которой описываются многие функции, позже обнаруженные во многих оболочках Unix.<ref> Шаблон:Cite web </ref><ref> Шаблон:Cite web </ref> Стандарт ASCII для кодировки символов был определен в 1969 году в документе под названием RFC 20.<ref> Шаблон:Cite web</ref>

Хронология

Ниже перечислены значимые события в истории Bash :

Различия в синтаксисе

Подавляющее большинство важных скриптов командного процессора Bourne может выполняться без изменения в bash, за исключением тех, которые ссылаются на специальные переменные Bourne или используют встроенные команды Bourne. Синтаксис команд Bash включает идеи, заимствованные у Korn shell (ksh) и C shell (csh), такие как редактирование командной строки, история команд, стек каталогов, переменные $RANDOM и $PPID, синтаксис замены команды $(…). Когда Bash используется как интерактивный командный процессор, он поддерживает автозавершение имён программ, файлов, переменных и т. п. с помощью клавиши Шаблон:Клавиша.

Внутренние команды

Интерпретатор bash имеет множество встроенных команд, часть из которых имеет аналогичные исполняемые файлы в операционной системе. Однако следует обратить внимание, что чаще всего для встроенных команд отсутствуют man-страницы, а при попытке просмотра справки по встроенной команде на самом деле будет выдаваться справка по исполняемому файлу. Исполняемый файл и встроенная команда могут различаться параметрами. Информация по встроенным командам расписана в справочной странице bash:

man bash

Ввод-вывод
echo выводит выражение или содержимое переменной (stdout), но имеет ограничения в использовании<ref>Невозможно вывести значение переменной, содержащей -n (в отличие от printf -- '%s\n' "${переменная}"), так как -n интерпретируется как параметр команды echo.</ref>
printf команда форматированного вывода, расширенный вариант команды echo
read «читает» значение переменной со стандартного ввода (stdin), в интерактивном режиме это клавиатура
Файловая система
cd изменяет текущий каталог
pwd выводит название текущего рабочего каталога (от англ. Шаблон:Lang-en2)
pushd изменяет текущий каталог с возможностью возврата в обратном порядке
popd возвращает текущий каталог после pushd
dirs выводит или очищает содержимое стека каталогов, сохранённых через pushd
Действия над переменными
let производит арифметические операции над переменными
eval транслирует список аргументов из списка в команды
set изменяет значения внутренних переменных скрипта
unset удаляет переменную
export экспортирует переменную, делая её доступной дочерним процессам
declare, typeset задают и/или накладывают ограничения на переменные
getopts используется для разбора аргументов, передаваемых скрипту из командной строки
Управление сценарием
source, . (точка) запуск указанного сценария
exit безусловное завершение работы сценария
exec заменяет текущий процесс новым, запускаемым командой exec
shopt позволяет изменять ключи (опции) оболочки «на лету»
Команды
true возвращает код завершения ноль (успешное завершение)
false возвращает код завершения, который свидетельствует о неудаче
type prog выводит полный путь к prog
hash prog запоминает путь к prog
help COMMAND выводит краткую справку по использованию внутренней команды COMMAND
Управление запущенными в командной оболочке задачами
jobs показывает список запущенных в командной оболочке задач либо информацию о конкретной задаче по её номеру
fg переключает поток ввода на текущую задачу (или на определённую задачу, если указан её номер) и продолжает её исполнение
bg продолжает исполнение текущей приостановленной задачи (или определённых задач, если указаны их номера) в фоновом режиме
wait ожидает завершения указанных задач

Скрипты

В простейшем случае скрипт — простой список команд, записанный в файл. Командный процессор должен знать, что он должен этот файл обработать, а не просто прочесть его содержимое. Для этого служит специальная конструкция, называемая shebang: #!. Символ # задаёт комментарий, но в данном случае shebang означает, что после этого спецсимвола находится путь к интерпретатору для исполнения сценария.

Синтаксис

Синтаксис команд bash — это расширенный синтаксис команд Bourne shell. Окончательная спецификация синтаксиса команд bash есть в Bash Reference Manual, распространяемом проектом GNU.<ref>Bash Reference Manual Шаблон:Wayback.</ref>

«Hello world»

<source lang="bash">

  1. !/usr/bin/env bash

echo 'Hello World!' </source>

Этот скрипт содержит только две строки. Первая строка сообщает системе о том, какая программа используется для запуска файла. Вторая строка — это единственное действие, которое выполняется этим скриптом, он собственно печатает «Hello world!» в терминале.

Запуск скрипта

Для того, чтобы скрипт стал исполняемым, могут быть использованы следующие команды: <source lang="bash"> chmod +rx scriptname # выдача прав на чтение/исполнение любому пользователю chmod u+rx scriptname # выдача прав на чтение/исполнение только «владельцу» скрипта </source>

Из соображений безопасности путь к текущему каталогу . не включён в переменную окружения $PATH. Поэтому для запуска скрипта необходимо явно указывать путь к текущему каталогу, в котором находится скрипт: <source lang="bash"> ./scriptname </source>

Кроме того, передать такой файл на исполнение интерпретатору Bash можно и явно, используя команду bash:

<source lang="bash"> bash scriptname </source>

В этом случае не требуется ни установка прав доступа, ни использование последовательности #! в коде.

Перенаправление ввода-вывода

Шаблон:См. также В bash есть встроенные файловые дескрипторы: 0 (stdin), 1 (stdout), 2 (stderr).

  • stdin — стандартный ввод — то, что набирает пользователь в консоли;
  • stdout — стандартный вывод программы;
  • stderr — стандартный вывод ошибок.

Для операций с этими и пользовательскими дескрипторами существуют специальные символы: > (перенаправление вывода), < (перенаправление ввода). Символы &, - могут предварять номер дескриптора; например, 2>&1 — перенаправление дескриптора 2 (stderr) в дескриптор 1 (stdout).

0<filename или <filename Перенаправление ввода из файла filename
1>filename или >filename Перенаправление вывода в файл «filename». Если отключена опция noclobber, то файл перезаписывается поступающими данными
1>|filename или >|filename Перенаправление вывода в файл «filename», файл перезаписывается поступающими данными
1>>filename или >>filename Перенаправление вывода в файл «filename», данные добавляются в конец файла. При отсутствии файла он создаётся
2>filename Перенаправление стандартного вывода ошибок в файл «filename»
2>>filename Перенаправление стандартного вывода ошибок в файл «filename», данные добавляются в конец файла. При отсутствии файла он создаётся
&>filename Перенаправление вывода и ошибок в файл «filename»
2>&1 Перенаправление вывода ошибок на стандартный вывод

Bash имеет индивидуальный синтаксис перенаправления, который не поддерживается в Bourne shell. Пример одновременного перенаправления стандартного вывода и стандартных ошибок: <source lang="bash"> command &> file </source> Это проще набрать, чем эквивалентную команду в синтаксисе Bourne shell <source lang="bash"> command > file 2>&1 </source>

Перенаправление «из кода скрипта»

Поддерживается heredoc-синтаксис:

  • С интерпретацией переменных и конструкций языка внутри блока:

<source lang="bash"> $a='многострочный' command <<MYDOC123 $a текст $(<$HOME/my_file.txt) MYDOC123 </source>

  • Без интерпретации переменных:

<source lang="bash"> command <<'PERLCODE' my $first='Hello'; my $second='world'; say join(', ',$first,$second),'!'; PERLCODE </source>

  • С удалением начальных отступов (поддерживаются только отступы табуляцией):

<source lang="bash"> command <<-'TABSTRIP'

   for ((i=0; i<10; i++))
   do
       echo "$i"
   done

TABSTRIP </source>

Начиная с версии 2.05b, bash может перенаправлять стандартный ввод из строки, используя следующий синтаксис «here strings»: <source lang="bash"> command <<< "string to be read as standard input" </source>

Если строка содержит пробелы, её следует заключить в кавычки или апострофы, либо экранировать пробелы обратной косой чертой.

Будьте внимательны: вводимая с использованием here strings строка содержит неявную последовательность завершения строки: либо 1 дополнительный байт line feed, либо 2 дополнительных байта: carriage return и line feed. <source lang=bash> cat -<<<'123' | wc -c

  1. Результат: 4

cat <(echo -n '123') | wc -c

  1. Результат: 3

wc -c <<<'123'

  1. Результат: 4

echo -n 123 | wc -c

  1. Результат: 3

</source>

Начиная с версии 4.1<ref>Шаблон:Cite web</ref> стало возможным указывать в одной строке терминирующую последовательность символов и, сразу за ней, — скобку. Это может быть полезно для присвоения переменной содержимого here-doc: <source lang=bash> var=$( cat -<<'TERMSEQ' Февраль. Достать чернил и плакать! Писать о феврале навзрыд, Пока грохочущая слякоть Весною чёрною горит. TERMSEQ) </source> При этом BASH будет сгенерировано предупреждающее сообщение.

Перенаправление для процесса в целом

Пример (перенаправление стандартного вывода в файл, запись данных, закрытие файла, сброс stdout): <source lang="bash">

  1. make Filedescriptor(FD) 6 a copy of stdout (FD 1)

exec 6>&1

  1. open file "test.data" for writing

exec 1>test.data

  1. produce some content

echo "data:data:data"

  1. close file "test.data"

exec 1>&-

  1. make stdout a copy of FD 6 (reset stdout)

exec 1>&6

  1. close FD6

exec 6>&- </source>

Открытие и закрытие файлов: <source lang="bash">

  1. open file test.data for reading

exec 6<test.data

  1. read until end of file

while read -u 6 dta do

 echo "$dta" 

done

  1. close file test.data

exec 6<&- </source>

Подстановка вывода команд

Захват вывода внешних команд: <source lang="bash">

  1. выполнить 'date' и поместить результат в VAR

VAR="$(date)" echo "$VAR" #выведет дату на момент вызова предыдущей строки </source>

При этом не поддерживаются строки с нуль-символом, заключительные переводы строк пропадают, в отличие от каналов и прочего файлового ввода-вывода.

Условный оператор

<source lang="bash">

  1. !/usr/bin/env bash

T1='foo' T2='bar' if $T1 == "$T2" then

 echo 'условие выполняется'

else

 echo 'условие не выполняется'

fi </source> Обратите внимание, что кавычки вокруг левой части необязательны.<ref>BashGuide/TestsAndConditionals Шаблон:Wayback — Greg’s Wiki.</ref>

Циклы

<source lang="bash">

  1. !/usr/bin/env bash

for i in "Номер "{1..10} do

 echo "$i"

done </source>

<source lang="bash" line="1">

  1. !/usr/bin/env bash

COUNTER=0 while $COUNTER -lt 10 # До тех пор, пока условие ИСТИННО (возвращает 0) выполнять тело цикла do

 echo The counter is $COUNTER
 let COUNTER=COUNTER+1

done </source>

<source lang="bash">

  1. !/usr/bin/env bash

i=0 until $i -eq 10 # До тех пор, пока условие ЛОЖНО (возвращает не 0) выполнять тело цикла do

 echo "$i"
 i=$(($i+1))

done </source>

<source lang="bash">

  1. !/usr/bin/env bash
  2. внутри двойных круглых скобок переменные можно писать в Си-стиле (без $ и разделяя пробелом операторы и операнды)

for (( i = 0; i < 10; i++ )) do echo -n "$i; " done </source>

Массивы

В bash реализованы только одномерные массивы. Индексами могут быть как целочисленные значения («обычный» массив), так и строки (ассоциативный массив, или «хеш»).

Несмотря на унификацию синтаксиса для работы с обычными и ассоциативными массивами, первые не являются разновидностью вторых ни с точки зрения конечного пользователя, ни с точки зрения внутренней логики самого интерпретатора.

Как естественное следствие поддержки «ассоциативных» ключей, в bash существует крайне ограниченная возможность эмуляции многомерных массивов.

Общие операции

Получить значение элемента как индексированного, так и ассоциативного массива можно:

  • По фиксированному значению индекса в линейном массиве или строки в ассоциативном:

<source lang="bash"> declare -a arrLinear=(11 22 33 44) declare -A arrAssoc=([city]='London' [index]='420224' ) vi=${arrLinear[3]} # vi=44 va=${arrAssoc['city']} # va='London' </source>

  • По значению переменной, при этом для индексированных массивов необязательно указывать сигил ($) перед именем переменной, используемой для индесации. Сигил перед переменной индекса обязателен в случае с ассоциативными массивами:

<source lang="bash"> declare -i n=3 vi=${arrLinear[$i]} # vi=44 vi=${arrLinear[i]} # аналогично предыдущему, но без сигила

declare index='city' va=${arrAssoc[$index]} # va='London', и это правильно va=${arrAssoc[index]} # va='420224', и это ошибочный результат, если подразумевалось [$index] va=${arrAssoc['index']} # va='420224' </source>

Получить строку, состоящую из всех<ref name="массивы с пробелами">Для получения действительно всех элементов, включая элементы из пробелов и пустые строки, обязательно использовать кавычки.</ref> элементов массива, разделённых пробелом. <source lang="bash"> values="${arr[@]}" </source>

Получить строку со всеми<ref name="массивы с пробелами"/> индексами или ключами массива, независимо от того, численные они или текстовые: <source lang="bash"> keys="${!arr[@]}" </source>

Осуществить массовую замену первого вхождения подстроки «MAY» на «MARCH» во всех<ref name="массивы с пробелами"/> элементах массива и вернуть строку, составленную из результирующих элементов массива, разделённых пробелом: <source lang="bash"> values="${arr[@]/MAY/MARCH}" </source> То же самое, но в каждом<ref name="массивы с пробелами"/> элементе массива будут заменены все вхождения подстроки «MAY»: <source lang="bash"> values="${arr[@]//MAY/MARCH}" </source>

До сих пор не все заявленные в документации возможности правильно работают для массивов. Например: <source lang="bash">[ -v 'имя_массива' ]</source> неправильно срабатывает для пустого массива.<ref>Здесь апострофы употреблены правильно.</ref>

Операции с индексированными массивами

Bash имеет поддержку одномерных массивов. Инициализировать элементы массива можно в виде: my_array[xx]. Также можно явно объявить массив в сценарии, с помощью директивы declare: <source lang="bash"> declare -a my_array </source> Обращаться к отдельным элементам массива можно с помощью фигурных скобок: "${my_array[xx]}".

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

1) <source lang="bash"> Array=(element1 element2 element3) </source> 2) <source lang="bash"> temp_array[0]=element1 temp_array[5]=element temp_array[9]=elementN </source>

Добавление элементов в конец индексированного массива: <source lang="bash"> declare -a arrAnimals arrAnimals=(dog elephant horse cow fox koala turtle)

  1. Выводим содержимое массива:

echo "${arrAnimals[@]}"

  1. В конец массива arrAnimals добавляем новый элемент: "pig"

arrAnimals+=(pig)

  1. И снова показываем содержимое массива:

echo "${arrAnimals[@]}" </source>

Получить первый элемент массива: <source lang="bash"> echo "${arrAnimals[0]}" </source>

Как индексированные, так и ассоциативные массивы поддерживают так называемые «срезы»: <source lang="bash">

  1. Ещё один способ получить первый элемент массива

echo "${arrAnimals[@]:0:1}"

  1. Вывести 3 элемента массива, начиная со 2-го:

echo "${arrAnimals[@]:2:3}" </source> Примечание: в случае с ассоциативными массивами порядок следования значений в общем случае будет случайным (определяется используемой хеш-функцией), поэтому операция среза на ассоциативном массиве хотя и допустима, но имеет крайне ограниченную область практического применения.

В массивах с числовыми индексами допустима «обратная» («негативная») адресация, позволяющая получить доступ к элементам, начиная с конца массива: <source lang="bash">

  1. Значение последнего элемента массива

echo "${arrAnimals[-1]}"

  1. Значение предпоследнего элемента массива

echo "${arrAnimals[-2]}"

  1. ... и т.д.

</source>

С помощью встроенной команды mapfile (синоним: readarray) можно отображать содержимое текстового файла в индексированный массив: <source lang="bash"> declare -a fileWithLogins mapfile fileWithLogins </etc/passwd for ((i=0; i<${#fileWithLogins[@]}; i++)) do echo "Line #$i: ${fileWithLogins[$i]}" done </source>

Операции с ассоциативными массивами

Начиная с версии 4.0 в bash появилась поддержка ассоциативных массивов (так называемых hash-массивов).

Для объявления ассоциативных массивов используется ключ -A встроенной команды declare: <source lang="bash"> declare -A hshArray </source>

Как и в случае с индексированными массивами, для заполнения ассоциативных массивов могут использоваться два различных синтаксиса:

1) <source lang="bash"> TheCapitalOf[Georgia]='Tbilisi' TheCapitalOf[Australia]='Canberra' TheCapitalOf[Pakistan]='Islamabad' </source> 2) <source lang="bash"> TheCapitalOf=([Georgia]='Tbilisi' [Australia]='Canberra' [Pakistan]='Islamabad') </source>

С помощью ассоциативных массивов можно имитировать поддержку многомерных массивов: <source lang="bash"> declare -A a # объявляет ассоциативный массив 'a' i=1; j=2 # инициализация нескольких индексов a[$i,$j]=5 # присвоение значения "5" в ячейку "$i,$j" (т.е. "1,2") echo ${a[$i,$j]} # вывод хранимых значений из "$i,$j" </source>

К сожалению, в текущих версиях bash скопировать содержимое одного ассоциативного массива в другой простым присваиванием невозможно. Данную проблему можно только обойти, для чего существуют два принципиально разных подхода:

1) Эмулировать объявление второго хеша «с нуля» путём копирования объявления первого хеша: <source lang="bash"> declare -A hsh1 hsh1=(...)

source <(declare -p hsh1 | sed 's/^declare -A hsh1/declare -A hsh2/') </source>

2) Перебрать все<ref name="массивы с пробелами"/> элементы хеша-источника и скопировать их в целевой хеш: <source lang="bash"> declare -A hsh1 hsh2 hsh1=(...)

for k in "${!hsh1[@]}" do hsh2["$k"]="${hsh1["$k"]}" done </source>

Безопасная работа с массивами

Массивы являются удобным способом передачи динамически сгенерированных аргументов в функции или команды. При этом каждый элемент массива представляет собой отдельный аргумент. <syntaxhighlight lang="bash"> args=( ls -l -a / ) ls "${args[@]}" # ls -l -a / ls ${args[@]} # ls -l -a / ls ${args[*]} # ls -l -a / </syntaxhighlight> Однако при подобном использовании массивов следует быть осторожным ввиду особенностей раскрытия массивов при использовании в качестве индексов специальных символов @ и *.

Если массив заключён в кавычки и раскрывается с помощью индекса @, то образуется строка из слов, где каждое слово — отдельный элемент массива. Однако если не заключить раскрытие массива в двойные кавычки, то может получиться совсем другой результат: пробелы, входящие в состав элементов массива, становятся разделителями слов.<syntaxhighlight lang="bash"> args=( -l -a '/home/user/Рабочий стол' ) ls "${args[@]}" # просмотр содержимого каталога '/home/user/Рабочий стол' ls ${args[@]} # ошибка: каталогов '/home/user/Рабочий' и './стол' не существует </syntaxhighlight> Массив с индексом *, заключённый в двойные кавычки, раскрывается в одну строку, соединяя все элементы массива через разделители, хранимые в переменной IFS. Если не указать двойные кавычки, то массив раскрывается аналогично раскрытию при использовании индекса @. <syntaxhighlight lang="bash"> args=( usr local bin ) IFS='/' ls "${args[*]}" # просмотр содержимого каталога '/usr/local/bin' IFS='/' ls ${args[*]} # поочерёдный просмотр содержимого каталогов '.', './usr', './local' и './bin' </syntaxhighlight> При создании массива из содержимого текстовой переменной необходимо учитывать возможное наличие пробелов в тексте. Например, в качестве одного из способов создания массива из строки с перечислением можно рассматривать замену символа-разделителя на пробел. Однако наличие пробелов в разделяемых элементах приведёт к дроблению самих элементов на части. <syntaxhighlight lang="bash"> array=( ${text//,/} ) # неправильно: текст в переменной 'text' мог содержать пробельные символы

IFS=',' array=( $text ) # правильно: раздельтельным символом является запятая. IFS=',' read -r -a array <<< "$text" # правильно (альтернативный вариант с перенаправлением содержимого переменной 'text' в команду 'read') </syntaxhighlight> К ошибкам может привести создание массива из текста, полученного в качестве вывода команд или из файла, так как не только переводы строк, но также и пробелы с символами табуляции по умолчанию будут считаться разделителями<ref>Шаблон:Cite web</ref>. <syntaxhighlight lang="bash"> array=( "$(ls)" ) # неправильно: пробелы в названии файлов могут разбить имя файла на два элемента массива

IFS=$'\n' array=( "$(ls)" ) # правильно: разделителем будет только перевод строк mapfile -t array < <(ls) # правильно: альтернативный вариант через встроенную команду mapfile </syntaxhighlight>

Конвейер

Конвейер передаёт вывод предыдущей команды на ввод следующей или на вход командного интерпретатора. Метод часто используется для связывания последовательности команд в единую цепочку. Конвейер обозначается символом вертикальной черты |.

Пример (grep работает как фильтр для стандартного вывода): <source lang="bash"> cat filename | grep pattern </source>

Логические операции

Логическое ИЛИ обозначается как ||. В операциях проверки условий оператор || возвращает 0 (success), если один из операндов имеет значение true (ИСТИНА).

Логическое И обозначается как &&. В операциях проверки условий оператор && возвращает 0 (success) тогда и только тогда, когда оба операнда имеют значение true (ИСТИНА).

Примечание: Возможная путаница в понимании возникает из-за того, что команда true (и успешное завершение любой команды) завершается с кодом возврата 0, success (false, наоборот, не 0), в то время как логическое значение true/false — отлично от нуля/равно нулю.

Примеры: <source lang="bash"> if false; then echo "successfully"; else echo "unsuccessfully"; fi unsuccessfully </source>

<source lang="bash"> let "a=(( 1 && 0 && 123))"; echo $?; echo $a 1 # Код завершения команды (нулевой результат вычисления арифметического выражения) 0 # Значение переменной "a", результат логической операции if (( 1 && 0 && 123)); then echo "true"; else echo "false"; fi false

let "a=(( 1 && 123 && -345 ))"; echo $?; echo $a 0 # Код завершения команды 1 # Значение переменной "a", результат логической операции if (( 1 && 123 && -345 )); then echo "true"; else echo "false"; fi true </source>

<source lang="bash"> false && echo "Успешное завершение" || echo "Неуспешное завершение" Неуспешное завершение </source>

Целочисленная математика

Bash может выполнять целочисленные вычисления внутри процесса, используя команду ((…)) и синтаксис переменной $((…))<ref>Устаревший вариант: $[…].</ref>, как показано ниже: <source lang="bash"> VAR=55 # Устанавливаем переменную VAR, равной 55 ((VAR = VAR + 1)) # Добавляем единицу к переменной VAR. Обратите внимание на отсутствие знака '$' ((VAR+=1)) # Сокращённая форма записи инкремента ((++VAR)) # Другой способ увеличения VAR на единицу. Выполняет префиксный инкремент ((VAR++)) # Другой способ увеличения VAR на единицу. Выполняет постфиксный инкремент echo $((VAR * 22)) # Умножаем VAR на 22 и передаем результат команде echo $[VAR * 22] # Устаревший способ сделать то же ((VAR<<3)) # Побитовый сдвиг влево (то же, что VAR*8) ((VAR>>3)) # Побитовый сдвиг вправо (то же, что VAR/8) </source>

Команда ((…)) также может использоваться в условных утверждениях, так как её исходный параметр — это 0 или 1, которые могут интерпретироваться как true или false: <source lang="bash"> if ((VAR == Y * 3 + X * 2)) then

 echo Yes 

fi ((Z > 23)) && echo Yes </source>

Команда ((…)) поддерживает следующие операторы сравнения: == != > < >= <=.

Bash не поддерживает вычисления внутри процесса с числами с плавающей точкой. Только командные процессоры Unix Korn shell (версия 1993 года) и zsh (начиная с версии 4.0) поддерживают эту возможность.

Список математических операций: +, -, *, /, ** (возведение в степень), % (деление по модулю, остаток от деления), let — позволяет использовать сокращения арифметических команд (сокращая количество используемых переменных; например: a += b эквивалентно a = a + b и т. п.).

Переменные и аргументы

Аргументы:

$$ pid текущего shell (самого процесса-сценария)
$! pid последнего процесса в фоновом режиме
$? код возврата последнего процесса (функции или скрипта)
$x где x — номер параметра, переданного скрипту ($1, $2 и т. д., $0 — последний запущенный скрипт)
$# количество аргументов командной строки
$* все<ref name="массивы с пробелами"/> аргументы в виде одной строки (слова)
$@ то же самое, что и $*, но при этом каждый<ref name="массивы с пробелами"/> параметр представлен как отдельная строка (слово)
$- список флагов, переданных сценарию
$_ содержит последний аргумент предыдущей команды

Встроенные переменные:

$BASH путь к исполняемому файлу bash
$BASHPID PID текущего bash * (см. Примечание)
$BASH_VERSINFO[n] массив, состоящий из 6 элементов, содержащий информацию о версии bash
$BASH_VERSION версия Bash, установленного в системе
$DIRSTACK содержимое вершины стека каталогов
$EDITOR заданный по умолчанию редактор
$EUID «эффективный» идентификационный номер пользователя (Effective User ID)
$FUNCNAME имя текущей функции
$GLOBIGNORE перечень шаблонных символов, которые будут проигнорированы при выполнении подстановки имён файлов (globbing)
$GROUPS группы, к которым принадлежит текущий пользователь
$HOME домашний каталог пользователя
$HOSTNAME сетевое имя хоста
$HOSTTYPE тип машины (идентифицирует аппаратную архитектуру)
$IFS разделитель полей во вводимой строке
$LC_COLLATE задаёт порядок сортировки символов, в операциях подстановки имён файлов и в поиске по шаблону
$LC_CTYPE определяет кодировку символов
$LINENO Номер строки исполняемого сценария
$MACHTYPE аппаратная архитектура
$OLDPWD прежний рабочий каталог
$OSTYPE тип операционной системы
$PATH путь поиска (включает в себя каталоги /usr/bin/, /usr/X11R6/bin/, /usr/local/bin и т. д.)
$PIPESTATUS Код возврата канала (конвейера)
$PPID PID (идентификатор) родительского процесса
$PS1 приглашение командной строки
$PS2 вторичное приглашение командной строки, выводится тогда, когда от пользователя ожидается дополнительный ввод. Обычно отображается как «>»
$PS3 третичное приглашение, выводится, когда пользователь должен сделать выбор в операторе select
$PS4 приглашение четвёртого уровня, выводится (в изменённом виде) в начале каждой строки отладочного вывода тогда, когда сценарий вызывается с ключом -x. Обычно отображается как «+», «++» и т. д.
$PWD рабочий (текущий) каталог
$REPLY переменная по умолчанию, куда записывается ввод пользователя, выполненный с помощью команды read
$SECONDS время работы сценария (в секундах)
$SHELLOPTS список допустимых опций интерпретатора (доступна только для чтения)
$SHLVL уровень вложенности shell
  • Примечание: отличается от $$ при определенных обстоятельствах, таких как подоболочки, которые не требуют повторной инициализации bash.

Пример:

$ echo $(echo $BASHPID $$)      $$       $BASHPID
              25680    16920    16920    16920
#             |        |        |        |
#             |        |        |        -- $BASHPID outside of the subshell
#             |        |        -- $$ outside of the subshell
#             |        -- $$ inside of the subshell
#             -- $BASHPID inside of the subshell


Регулярные выражения внутри процесса

Bash 3.0 поддерживает встроенные регулярные выражения с синтаксисом, подобным синтаксису Perl: <source lang="bash"> string =~ regex </source> Синтаксис регулярных выражений задокументирован на страницах документации man 7 regex. Статус выхода устанавливается в 0, если регулярное выражение совпало со строкой, и 1, если нет. Значение подвыражения, заключённого в скобки, можно получить<ref name="массивы с пробелами"/> через переменную ${BASH_REMATCH[@]}, например: <source lang="bash"> REGEXP='foo(bar)bl(.*)' if "abcfoobarbletch" =~ $REGEXP then

 echo "Регулярное выражение совпало со строкой!" 
 echo "$BASH_REMATCH"      # выводит: foobarbletch 
 echo "${BASH_REMATCH[1]}" # выводит: bar 
 echo "${BASH_REMATCH[2]}" # выводит: etch 

fi </source>

Встроенные регулярные выражения обычно работают быстрее, чем выполнение внешней команды grep, потому что соответствующее регулярное выражение выполняется в рамках процесса bash. Если регулярное выражение или строка содержат пробелы или метасимволы (такие как * или ?), их следует взять в кавычки. Рекомендуется использовать переменную для хранения регулярного выражения, как в вышеприведённом примере, для избежания проблем с экранированием специальных символов. Можно использовать вывод bash с опцией -x для проверки, как именно bash воспринимает ваше регулярное выражение.

Расширение скобок

Возможность расширения скобок заимствована у csh. Она позволяет произвольной строке быть сформированной с использованием похожей техники, как это делается с названиями файлов. Однако в bash сгенерированные строки не обязаны быть именами файлов. Результат каждого расширения строки не сортируется, сохраняется порядок слева направо: <source lang="bash">

  1. Это особенность присущая bash

echo a{p,c,d,b}e # ape ace ade abe </source>

Не следует использовать эту особенность, если скрипт планируется портировать, потому что в традиционных скриптах расширение строки не будет действовать: <source lang="bash">

  1. Традиционная оболочка не даёт тот же результат

echo a{p,c,d,b}e # a{p,c,d,b}e </source>

Когда используется расширение скобок в сочетании с символами подстановки, скобки раскрываются первыми, а затем результат обрабатывается в обычном режиме. Таким образом, список JPEG- и PNG-изображений в текущем каталоге может быть получен так: <source lang="bash"> ls *.{jpg,jpeg,png} # скобки раскрываются до *.jpg *.jpeg *.png, после чего выполняется поиск по маскам </source>

Горячие клавиши

Стартовые скрипты

Bash при запуске вызывает команды из множества различных скриптов.

Когда bash вызывается как интерактивная оболочка входа в систему, первым делом он читает и вызывает команды из файла /etc/profile, если этот файл существует. После чтения этого файла он смотрит следующие файлы в следующем порядке: ~/.bash_profile, ~/.bash_login и ~/.profile, читает и вызывает команды из первого, который существует и доступен для чтения. При выходе bash читает и выполняет команды из файла ~/.bash_logout.

Когда запускается интерактивная оболочка, но не для входа в систему, bash читает и исполняет команды из файлов /etc/bash.bashrc и ~/.bashrc, если они существуют. Это может быть отменено опцией -norc. Опция -rcfile file заставит bash использовать команды из файла file вместо /etc/bash.bashrc и ~/.bashrc.

Переносимость

Первой строкой скрипта должна быть запись #!/bin/bash, если известен абсолютный путь к исполняемому файлу, либо #!/usr/bin/env bash для автоматического определения пути к исполняемому файлу через команду env с помощью переменной окружения PATH<ref>Шаблон:Cite web</ref>.

Скрипты оболочек, написанные со специфическими для bash особенностями, не будут работать на системах, где используется Bourne shell (sh) или один из его аналогов, если bash не был установлен в качестве дополнительной оболочки. Эта проблема стала особенно важной, когда Ubuntu начал с октября 2006 года поставлять Debian Almquist shell (dash) как скриптовую оболочку по умолчанию, что привело к неработоспособности многочисленных скриптов.

Графический интерфейс к скриптам

Существует множество программ, позволяющих создавать графический интерфейс к bash-скриптам.

  • dialog — утилита, позволяющая создавать диалоговые окна в консоли, использует библиотеки curses и ncurses.
  • whiptail — аналог утилиты dialog, использует библиотеку newt.
  • zenity — наиболее популярное приложение для создания графического интерфейса к скриптам.
  • kdialog — аналог zenity в среде KDE.
  • yad — форк zenity, с большими возможностями.
  • xdialog — замена dialog, предназначенная для придания запускаемым из терминала программам интерфейса X Window System.
  • gtkdialog — наиболее функциональная утилита для создания графических приложений на bash-скриптах.

См. также

Примечания

Шаблон:Примечания

Ссылки

Шаблон:Команды Unix Шаблон:Интерфейсы пользователя в Unix-подобных системах Шаблон:GNU Шаблон:POSIX.1-2008