Bash: различия между версиями
Материал из lulzette's wiki
Losted (обсуждение | вклад) Нет описания правки |
Losted (обсуждение | вклад) |
||
(не показано 15 промежуточных версий 2 участников) | |||
Строка 1: | Строка 1: | ||
oh-my-bash: https://github.com/ohmybash/oh-my-bash <br> | [[Category:Админство (Ops)]] | ||
Красивости (oh-my-bash): https://github.com/ohmybash/oh-my-bash <br> | |||
[[awk]] | AWK: [[awk]] | ||
http://mywiki.wooledge.org/BashPitfalls | Tips&Tricks: http://mywiki.wooledge.org/BashPitfalls | ||
<br> | |||
Цикл статей от RuVDS: https://habr.com/ru/company/ruvds/blog/325522/ | |||
[https://ruvds.com/doc/bash.pdf И в виде одного PDF] | |||
OpenNet: https://www.opennet.ru/docs/RUS/bash_scripting_guide/c2171.html | |||
Подробная Bash Hackers Wiki: https://wiki.bash-hackers.org/start | |||
==Работа с текстом== | |||
* (e)grep - показ нужных строк | |||
* sed - вырезать/заменить/удалить что-нибудь | |||
* <span style="font-family: inherit; font-size: 1rem;">tr - заменить один символ на другой</span> | |||
* <span style="font-family: inherit; font-size: 1rem;">cut - отрезать N символов от строки с начала или конца</span> | |||
* <span style="font-family: inherit; font-size: 1rem;">rev - реверс строки</span> | |||
===(e)grep=== | |||
grep - покажет только те строки, которые соответствуют строке. Например | |||
<source> | |||
$ echo "hello cocksucker" | grep cocksucker | |||
hello cocksucker | |||
$ echo "hello world" | grep cocksucker | |||
</source> | |||
С помощью egrep можно играться с регулярками | |||
<source> | |||
$ echo "hello world" | egrep 'cocksucker|world' | |||
hello world | |||
</source> | |||
Я часто использую эти: | |||
<source> | |||
| - или | |||
.* - любое количество символов | |||
.? - только один любой символ | |||
</source> | |||
Также есть полезные параметры: | |||
<source> | |||
-v - наоборот, вывести все кроме указанных строк | |||
-c - подсчитать количество совпадений | |||
-HlR - Вывести название файла, не выводить строку, рекурсивно (по всем файлам в директории) | |||
</source> | |||
=== cut === | |||
https://losst.ru/komanda-cut-linux | |||
Обрезаем символы/байты/поля. Пример с символами: | |||
<source> | |||
$ echo hello cock | cut -c1-4 [22:34:47] | |||
hell | |||
losted@arch-llz: ~ | |||
$ echo hello cock | cut -c4-7 [22:34:52] | |||
lo c | |||
losted@arch-llz: ~ | |||
$ echo hello cock | cut -c-4 [22:36:02] | |||
hell | |||
losted@arch-llz: ~ | |||
$ echo hello cock | cut -c4- [22:34:57] | |||
lo cock | |||
</source> | |||
=== tr === | |||
Нечего сказать. Просто заменяет один символ на другой по всему stdin | |||
Например, уберем дробные числа (оставим только названия серверов) и заменим перевод строки (\n) на запятую ",": | |||
<source> | |||
$ echo "bitrix374 | |||
94.57 | |||
bitrix378 | |||
96.61 | |||
vh382 | |||
96.88 | |||
vh388 | |||
97.91 | |||
... | |||
vh314 | |||
98.78 | |||
vh80 | |||
98.78 | |||
vh172 | |||
98.96 | |||
vh132 | |||
99.13 | |||
bone020 | |||
99.13" | grep -v '\.' | tr '\n' ',' | |||
bitrix374,bitrix378,vh382,vh388,vh362,vh280,bitrix362,vh278,vh376,vh254,vh270,vh38,shirley,vh276,vh186,vh314,vh80,vh172,vh132,bone020, | |||
</source> | |||
== if == | == if == | ||
* Квадратные скобки - if логический. | |||
* Круглые скобки - if арифметический | |||
https://www.gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html | |||
* <code>[ *условие* ] && команда </code> - выполнит команду если условие верно | * <code>[ *условие* ] && команда </code> - выполнит команду если условие верно | ||
* <code>[ *условие* ] || команда </code> - выполнит команду если условие ложно | * <code>[ *условие* ] || команда </code> - выполнит команду если условие ложно | ||
Условия-проверки: | |||
< | https://www.shellhacks.com/ru/bash-test-if-file-exists/ | ||
* <code>-e</code> - файл (любой) существует | |||
* <code>-f</code> - файл (простой) существует | |||
* <code>-d</code> - директория существует | |||
Условия-сравнения: | |||
* <code>-z</code> — строка пуста | |||
- | * <code>-n</code> — строка не пуста | ||
- | * <code>-eq</code> или <code>=, ( == )</code> — равно | ||
= | * <code>-ne</code> или <code>!=</code> — неравно | ||
* <code>-lt,(< )</code> — меньше | |||
- | * <code>-le,(<=)</code> — меньше или равно | ||
- | * <code>-gt,(>)</code> — больше | ||
- | * <code>-ge,(>=)</code> — больше или равно | ||
<quote> | |||
Приведу список логических операторов, которые используются для if|then|else: | |||
=, ( == ) — строки равны | |||
!= — строки неравны | |||
! — отрицание логического выражения | ! — отрицание логического выражения | ||
Строка 48: | Строка 162: | ||
-o,(||) — логическое «ИЛИ» | -o,(||) — логическое «ИЛИ» | ||
</ | </quote> | ||
== Башизмы == | |||
=== Работа с файлами === | |||
Объём всех файлов/папок включая скрытые в текущей директории: | |||
<syntaxhighlight lang="bash"> | |||
du -hs * .[^.]* | |||
</syntaxhighlight><br> | |||
Перебор файлов в папке (echo заменить на требуемую команду): | |||
<syntaxhighlight lang="bash"> | |||
for file in *; do echo $file; done; | |||
# Например, для импорта большого количества таблиц БД: | |||
for file in *; do mysql -u'USER' DB -p'PASS' < $file; done; | |||
</syntaxhighlight><br> | |||
Если найдет sometext в файле из папки /some/dir, то скопирует всё содержимое этого файла в somefile.txt | |||
<syntaxhighlight lang="bash"> | |||
grep -lR "sometext" /some/dir | xargs cat >> somefile.txt | |||
</syntaxhighlight><br> | |||
Обединить сожержимое нескольких файлов в один (somefile), file* это шаблон для поиска нужных файлов: | |||
<syntaxhighlight lang="bash"> | |||
ls -1 file* | xargs -n 1 -I {} cat {} >> somefile | |||
</syntaxhighlight><br> | |||
=== Работа с текстом === | |||
Прочитать файл построчно и выполнить действие над строками (echo заменить на требуемую команду): | |||
<syntaxhighlight lang="bash"> | |||
while IFS= read -r line; do echo $line; done < file.txt | |||
</syntaxhighlight><br> | |||
Найти все вхождения подстроки (будет выведено каждое вхождение, для их подсчёта использовать `wc -l`): | |||
<syntaxhighlight lang="bash"> | |||
cat file.txt | grep -o "pattern" | |||
</syntaxhighlight><br> | |||
Удалить подстроку из STRING, найденную по регулярке PATTERN (работает только с gawk): | |||
<syntaxhighlight lang="bash"> | |||
PATTERN='regexp' # регулярку regexp необходимо записывать без операторных скобок (слэшей) вокруг | |||
echo "$STRING" | awk -v pattern="$PATTERN"\ | |||
'match($0, pattern, matches)\ | |||
{ | |||
ext=matches[0]"$"; | |||
sub(ext, ""); | |||
print $0 | |||
}' | |||
</syntaxhighlight><br> | |||
Поиск файлов с именами определённой длины. find найдёт все файлы с длиной имени от 3 до 5 символов не учитывая расширение (предусмотрено наличие точек и пробелов в имени): | |||
<syntaxhighlight lang="bash"> | |||
find . -type f -regextype posix-egrep -regex ".*/(.{3,5})\.([^\.]+)$" | |||
</syntaxhighlight><br> | |||
Направить файл в stdin, строки в одну строку и разделены пробелами: | |||
<syntaxhighlight lang="bash"> | |||
$ cat file.txt | |||
one | |||
two | |||
$ echo $(< file.txt) | |||
one two | |||
</syntaxhighlight><br> | |||
Удалить из файла строки, содержащие паттерн: | |||
<syntaxhighlight lang="bash"> | |||
sed -i '/pattern/d' foobar.txt | |||
</syntaxhighlight><br> | |||
=== Работа со строками === | |||
Вывести длину строки: | |||
<syntaxhighlight lang="bash"> | |||
str='onetwo'; echo ${#str} # в результате 3 | |||
</syntaxhighlight><br> | |||
Удалить пробелы в строке: | |||
<syntaxhighlight lang="bash"> | |||
str='one two'; echo ${str//[[:blank:]]/} | |||
# или | |||
echo 'one two' | sed 's/ //g' | |||
</syntaxhighlight><br> | |||
Количество слов в строке: | |||
<syntaxhighlight lang="bash"> | |||
echo 'one two' | wc -w # в результате 2 | |||
</syntaxhighlight><br> | |||
Найти вхождение между левым и правым выражениями: | |||
<syntaxhighlight lang="bash"> | |||
echo "Here is a String" | sed -e 's/Here\(.*\)String/\1/' # результат: "is a" | |||
</syntaxhighlight><br> | |||
Замена подстроки и обрезка строки: | |||
<syntaxhighlight lang="bash"> | |||
echo "${PWD//${HOME::(-1)}/\~}" | |||
# В примере выше производится замена пути "/home/user" на "~/". | |||
# $HOME содержит путь "/home/user/", поэтому вырезается последний символ тут: ${HOME::(-1)} | |||
</syntaxhighlight><br> |
Текущая версия от 22:38, 27 декабря 2021
Красивости (oh-my-bash): https://github.com/ohmybash/oh-my-bash
AWK: awk
Tips&Tricks: http://mywiki.wooledge.org/BashPitfalls
Цикл статей от RuVDS: https://habr.com/ru/company/ruvds/blog/325522/
OpenNet: https://www.opennet.ru/docs/RUS/bash_scripting_guide/c2171.html
Подробная Bash Hackers Wiki: https://wiki.bash-hackers.org/start
Работа с текстом
- (e)grep - показ нужных строк
- sed - вырезать/заменить/удалить что-нибудь
- tr - заменить один символ на другой
- cut - отрезать N символов от строки с начала или конца
- rev - реверс строки
(e)grep
grep - покажет только те строки, которые соответствуют строке. Например
$ echo "hello cocksucker" | grep cocksucker
hello cocksucker
$ echo "hello world" | grep cocksucker
С помощью egrep можно играться с регулярками
$ echo "hello world" | egrep 'cocksucker|world'
hello world
Я часто использую эти:
| - или
.* - любое количество символов
.? - только один любой символ
Также есть полезные параметры:
-v - наоборот, вывести все кроме указанных строк
-c - подсчитать количество совпадений
-HlR - Вывести название файла, не выводить строку, рекурсивно (по всем файлам в директории)
cut
https://losst.ru/komanda-cut-linux
Обрезаем символы/байты/поля. Пример с символами:
$ echo hello cock | cut -c1-4 [22:34:47]
hell
losted@arch-llz: ~
$ echo hello cock | cut -c4-7 [22:34:52]
lo c
losted@arch-llz: ~
$ echo hello cock | cut -c-4 [22:36:02]
hell
losted@arch-llz: ~
$ echo hello cock | cut -c4- [22:34:57]
lo cock
tr
Нечего сказать. Просто заменяет один символ на другой по всему stdin
Например, уберем дробные числа (оставим только названия серверов) и заменим перевод строки (\n) на запятую ",":
$ echo "bitrix374
94.57
bitrix378
96.61
vh382
96.88
vh388
97.91
...
vh314
98.78
vh80
98.78
vh172
98.96
vh132
99.13
bone020
99.13" | grep -v '\.' | tr '\n' ','
bitrix374,bitrix378,vh382,vh388,vh362,vh280,bitrix362,vh278,vh376,vh254,vh270,vh38,shirley,vh276,vh186,vh314,vh80,vh172,vh132,bone020,
if
- Квадратные скобки - if логический.
- Круглые скобки - if арифметический
https://www.gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html
[ *условие* ] && команда
- выполнит команду если условие верно[ *условие* ] || команда
- выполнит команду если условие ложно
Условия-проверки:
https://www.shellhacks.com/ru/bash-test-if-file-exists/
-e
- файл (любой) существует
-f
- файл (простой) существует
-d
- директория существует
Условия-сравнения:
-z
— строка пуста
-n
— строка не пуста
-eq
или=, ( == )
— равно
-ne
или!=
— неравно
-lt,(< )
— меньше
-le,(<=)
— меньше или равно
-gt,(>)
— больше
-ge,(>=)
— больше или равно
<quote> Приведу список логических операторов, которые используются для if|then|else:
=, ( == ) — строки равны
!= — строки неравны
! — отрицание логического выражения
-a,(&&) — логическое «И»
-o,(||) — логическое «ИЛИ» </quote>
Башизмы
Работа с файлами
Объём всех файлов/папок включая скрытые в текущей директории:
du -hs * .[^.]*
Перебор файлов в папке (echo заменить на требуемую команду):
for file in *; do echo $file; done;
# Например, для импорта большого количества таблиц БД:
for file in *; do mysql -u'USER' DB -p'PASS' < $file; done;
Если найдет sometext в файле из папки /some/dir, то скопирует всё содержимое этого файла в somefile.txt
grep -lR "sometext" /some/dir | xargs cat >> somefile.txt
Обединить сожержимое нескольких файлов в один (somefile), file* это шаблон для поиска нужных файлов:
ls -1 file* | xargs -n 1 -I {} cat {} >> somefile
Работа с текстом
Прочитать файл построчно и выполнить действие над строками (echo заменить на требуемую команду):
while IFS= read -r line; do echo $line; done < file.txt
Найти все вхождения подстроки (будет выведено каждое вхождение, для их подсчёта использовать `wc -l`):
cat file.txt | grep -o "pattern"
Удалить подстроку из STRING, найденную по регулярке PATTERN (работает только с gawk):
PATTERN='regexp' # регулярку regexp необходимо записывать без операторных скобок (слэшей) вокруг
echo "$STRING" | awk -v pattern="$PATTERN"\
'match($0, pattern, matches)\
{
ext=matches[0]"$";
sub(ext, "");
print $0
}'
Поиск файлов с именами определённой длины. find найдёт все файлы с длиной имени от 3 до 5 символов не учитывая расширение (предусмотрено наличие точек и пробелов в имени):
find . -type f -regextype posix-egrep -regex ".*/(.{3,5})\.([^\.]+)$"
Направить файл в stdin, строки в одну строку и разделены пробелами:
$ cat file.txt
one
two
$ echo $(< file.txt)
one two
Удалить из файла строки, содержащие паттерн:
sed -i '/pattern/d' foobar.txt
Работа со строками
Вывести длину строки:
str='onetwo'; echo ${#str} # в результате 3
Удалить пробелы в строке:
str='one two'; echo ${str//[[:blank:]]/}
# или
echo 'one two' | sed 's/ //g'
Количество слов в строке:
echo 'one two' | wc -w # в результате 2
Найти вхождение между левым и правым выражениями:
echo "Here is a String" | sed -e 's/Here\(.*\)String/\1/' # результат: "is a"
Замена подстроки и обрезка строки:
echo "${PWD//${HOME::(-1)}/\~}"
# В примере выше производится замена пути "/home/user" на "~/".
# $HOME содержит путь "/home/user/", поэтому вырезается последний символ тут: ${HOME::(-1)}