Действия

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

Материал из lulzette's wiki

Нет описания правки
 
(не показано 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> - выполнит команду если условие ложно


* <code>[ -f path ]</code> - Наличие файла
Условия-проверки:
* <code>[ -d path ]</code> - Наличие директории


<source>
https://www.shellhacks.com/ru/bash-test-if-file-exists/
Скобки
 
[ — является специальной встроенной командой test воспринимающей свои аргументы как выражение сравнения или файловую проверку […..].
* <code>-e</code> - файл (любой) существует
 
* <code>-f</code> - файл (простой) существует


[[ — расширенный вариант от «[«, является зарезервированным словом, а не командой, его bash выполняет как один элемент с кодом возврата. Внутри «[[….]]» разрешается выполнение операторов &&, || которые приводят к ошибке в обычных скобках «[….]» тем самым вариант с двойной скобкой более универсален.
* <code>-d</code> - директория существует


(( — является арифметическими выражениями, которое так же возвращают код 0. Тем самым такие выражения могут участвовать в операциях сравнения.
Условия-сравнения:


Приведу список логических операторов, которые используются для if|then|else:
* <code>-z</code>  — строка пуста


-— строка пуста
* <code>-n</code> — строка не пуста


-n строка не пуста
* <code>-eq</code> или <code>=, ( == )</code> равно


=, ( == ) строки равны
* <code>-ne</code> или <code>!=</code> неравно


!=  строки неравны
* <code>-lt,(< )</code> меньше


-eq — равно
* <code>-le,(<=)</code> меньше или равно


-ne неравно
* <code>-gt,(>)</code> больше


-lt,(< ) меньше
* <code>-ge,(>=)</code> больше или равно


-le,(<=) — меньше или равно
<quote>
Приведу список логических операторов, которые используются для if|then|else:


-gt,(>) — больше
=, ( == ) — строки равны


-ge,(>=) больше или равно
!= строки неравны


! — отрицание логического выражения
! — отрицание логического выражения
Строка 48: Строка 162:


-o,(||) — логическое «ИЛИ»
-o,(||) — логическое «ИЛИ»
</source>
</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/

И в виде одного 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 - вырезать/заменить/удалить что-нибудь
  • 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)}