Bash Считываем файл построчно

И так, в bash-е, для того, что бы считать файл построчно:

#!/bin/bash
file="/home/osticket/data.txt"
while IFS= read -r line
do
# display $line or do somthing with $line
echo "$line"
done <"$file"

или

#!/bin/bash
file="/home/osticket/data.txt"
while read line
do
# display $line or do somthing with $line
echo "$line"
done < $file

Строка будет записываться в переменную $line

Bash Считам количество букв в строке

И так, для подсчета количества букв воспользуемся командой grep. Как пример давайте посчитает количество букв ‘s’ в переменной $x:

x=»This is a test»
grep -o «s» <<<«$x» | wc -l

результат будет:

3

Для того, что бы посчитать ‘s’ и ‘S’:

x=»This is a test. S»
grep -o «[s|S]» <<<«$x» | wc -l

результат:

4

Используя только bash:

x=»This is a test»
y=»${x//[^s]}»
echo «$y»
echo «${#y}»

Для того, что бы посчитать ‘s’ и ‘S’:

x=»This is a test. S»
y=»${x//[^s|S]}»
echo «${#y}»

Bash Удаляем пустые папки

Тут на медне у меня ушли в мир иной пара винтов на сервере, которые были в одной LVM разделе. Бакапы давно никто не снимал, а информация с них была нужна. В общем после восстановления раздела, и проходы по нему fsck-ом, образовалась масса папочек, и многие из них были пустыми, так вот, что бы удалить все пустые папки, вы можете воспользоваться следующим:

find -depth -type d -empty -exec rmdir {} \;

Bash Ждать пока не завершится процесс

Бывает, что в bash скрипте необходимо подождать пока не завершиться какой-то процесс. Если вы знаете его pid, то это можно реализовать так:

while ps -p `cat $PID_FILE` > /dev/null; do sleep 1; done

Bash скрипт универсальный распаковщик

Надоело мне для каждой программы сжатия использовать свои программы и ключи, и вылился этот порыв вот в такой скрипт:

#!/bin/bash
#
#

Z="compress -d"
gz="gunzip"
bz="bunzip2"
zip="unzip -qo"
rar="unrar x -id -y"
tar="tar xf"
7z="p7zip -d"

if [ $# -eq 0 ]; then
    echo "Usage: decompress file or files">&2
    exit 1
fi

for name
do
	if [ ! -f "$name" ] ; then
		echo "$0: file $name not found." >&2
		continue
	fi

	if [ "$(echo $name | egrep '(\.Z$|\.gz$|\.bz2$|\.zip$|\.rar$|\.tar$|\.tgz$|\.7z$)')" = "" ] ; then
		echo "Skipped file ${name}: it's already decompressed." 
      		continue
	fi

	extension=${name##*.}

	case "$extension" in
		Z ) echo "Filetype is Z. Decompressing..."
		    $Z "$name"
		    ;;
		gz ) echo "Filetype is gz. Decompressing..."
		     $gz "$name"
		     ;;
		bz2 ) echo "Filetype is bz2. Decompressing..."
 		     $bz "$name"
		     ;;
		zip ) echo "Filetype is zip. Decompressing..."
		      $zip "$name"
		      ;;
		rar ) echo "Filetype is rar. Decompressing..."
		      $rar "$name"
		      ;;
		tar ) echo "Filetype is tar. Decompressing..."
              	      $tar "$name"
              	      ;;
		tgz ) echo "Filetype is tgz. Decompressing..."
              	      $tar "$name"
                     ;;
               7z ) echo "Filetype is 7z. Decompressing..."
                     $7z "$name"
	esac

done

exit 0


Bash Убираем коментарии в файле

Я думаю каждый администратор сталкивался с такой проблемой, когда нужно убрать все закоментированые строки в конфигурационном файле или скрипте. Для этого вы можете воспользоваться вот таким скриптом:

#!/bin/bash
#
#
sed '1p; /^[[:blank:]]*#/d; s/[[:blank:]][[:blank:]]*#.*//' $1 > new

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

#!/bin/bash
#
#
sed '1p; /^[[:blank:]]*#/d; s/[[:blank:]][[:blank:]]*#.*//' $1 | sed -e 's/[\t ]//g;/^$/d' > new

 

Bash нюансы. Часть 1. Значение по умолчанию для переменных

Не все знают, что в bash  есть возможность назначить входной переменной параметр по умолчанию. Как пример, если параметр $1 не задан то использовать root:

user=${1:-root}

Еще один пример использования:

#!/bin/bash
dir="${1:-/tmp}"
cp * $dir
echo "Все скопировано в ${dir}"

Вы так же можете назначить значение по умолчанию обычной переменной. Как пример выведем значение параметра $VAR при помощи echo, при этом, если $VAR не задан то присвоить значение parametr:

echo ${VAR:=parametr}

Важно помнить, что со специальными параметрами, такими как например $1 необходимо использовать конструкцию ${var:-defaultValue}
 

Часть 1. Значение по умолчанию для переменных
Часть 2. Длинна переменной

Bash Авто перезапуск процесса

Простой скрипт который вы можете поставить в cron для перезапуска процесса.

#!/bin/bash
PGREP="/usr/bin/pgrep"
RUN=$1

$PGREP ${RUN}

if [ $? -ne 0 ]
then
$2
fi

Использовать его не сложно, первым идет название процесса за которым мы следим, вторым — команда на перезапуск, как пример, пусть скрипт называется restart.sh, а проверят мы будем Apache. Тогда в cron добавляем:

*/5 * * * * /restart.sh httpd ‘service httpd restart’ &> /dev/null

Bash учебное пособие. Часть 7: Подмножества и части строк. Размеры

Подмножества и части строк

Обычно расширение имеет такую форму: ${PARAMETER:OFFSET:LENGTH}, где аргумент LENGTH необязателен. Итак, если вы хотите выбрать только определенное подмножество аргументов скрипта, вы можете использовать полную версию, чтобы показать, сколько аргументов следует выбрать. Например, ${@:4:3} обращается к трем аргументам, начиная с аргумента 4, а именно, к аргументам 4, 5 и 6. Вы можете использовать это расширение для выбора конкретных параметров помимо тех, которые доступны сразу, используя от $1 до $9 включительно. ${@:15:1} — способ вызова сразу 15 параметра.

Вы можете использовать расширение с конкретными параметрами, а также весь набор параметров, представленный при помощи $* или $@. В этом случае параметр обрабатывается как строка и число, представляющее собой сдвиг или длину. Например, если переменная x имеет значение «some value», то

${x:3:5}

будет иметь значение «e val».

Подстроки значений параметров в shell

[root@httpd ~]$ x=»some value»
[root@httpd ~]$ echo «${x:3:5}»
e val

Размеры

Вы уже видели, что $# указывает число параметров и что расширение ${PARAMETER:OFFSET:LENGTH} применяется и к конкретным параметрам, и к $* и $@, поэтому вас не должно удивить, что аналогичная конструкция, ${#PARAMETER}, может использоваться для определения размера конкретного параметра. Простая функция testlength, показанная в Листинге 10, иллюстрирует это. Попробуйте сделать это сами.

Параметр lengths

[root@httpd ~]$ testlength () { for p in «$@»; do echo ${#p};done }
[root@httpd ~]$ testlength 1 abc «def ghi»
1
3
7

Работа с шаблонами

Расширение параметра также включает возможности поиска по шаблону при помощи тех же знаков подстановки, которые используются в расширениях имен файлов или подстановках. Обратите внимание, что это не соответствует регулярным выражениям, используемым grep.

Расширение шаблонов в shell Расширение Назначение

${ПАРАМЕТР#СЛОВО} Shell расширяет СЛОВО как расширение имени файла и удаляет самое короткое соответствие шаблону, если оно имеется, с начала расширенного значения ПАРАМЕТРА. Использование ‘@’ или ‘$’ приводит к удалению по образцу для каждого параметра в списке.
${ПАРАМЕТР##СЛОВО} Приводит к удалению самого длинного соответствия шаблону с начала вместо самого короткого.
${ПАРАМЕТР%СЛОВО} Shell расширяет СЛОВО как расширение имени файла и удаляет самое короткое соответствие шаблону, если оно имеется, с конца расширенного значения ПАРАМЕТРА. Использование ‘@’ или ‘$’ приводит к удалению по образцу для каждого параметра в списке.
${ПАРАМЕТР%%СЛОВО} Приводит к удалению самого длинного соответствия шаблону с конца вместо самого короткого.
${ПАРАМЕТР/ОБРАЗЕЦ/ПОСЛЕДОВАТЕЛЬНОСТЬ} Shell расширяет ОБРАЗЕЦ как расширение имени файла и заменяет самое длинное соответствие шаблону, если оно имеется, расширенным значением ПАРАМЕТРА. Для соответствия образцам в начале расширенного значения ПАРАМЕТРА поставьте в начале ОБРАЗЦА # или %, если соответствие должно проверяться до конца. Если ПОСЛЕДОВАТЕЛЬНОСТЬ пуста, перемещение / может быть опущено и соответствия удаляются. Использование ‘@’ или ‘$’ приводит к замене образца для каждого параметра в списке.
${ПАРАМЕТР//ОБРАЗЕЦ/ПОСЛЕДОВАТЕЛЬНОСТЬ} Выполняет замену для всех подходящих, а не только для первого.

Примеры шаблонов

[root@httpd ~]$ x=»a1 b1 c2 d2″
[root@httpd ~]$ echo ${x#*1}
b1 c2 d2
[root@httpd ~]$ echo ${x##*1}
c2 d2
[root@httpd ~]$ echo ${x%1*}
a1 b
[root@httpd ~]$ echo ${x%%1*}
a
[root@httpd ~]$ echo ${x/1/3}
a3 b1 c2 d2
[root@httpd ~]$ echo ${x//1/3}
a3 b3 c2 d2
[root@httpd ~]$ echo ${x//?1/z3}
z3 z3 c2 d2

Часть 1: скрипт Hellow World
Часть 2: Переменные
Часть 3: Специальные параметры
Часть 4: Одинарные и двойные кавычки. Математические операции
Часть 5: Структурные конструкции и команда test
Часть 6: Структура If…then…else
Часть 7: Подмножества и части строк. Размеры

Bash учебное пособие. Часть 6: Структура If…then…else

if…else…fi позволяют вам сделать выбор основанный на справедливости выражения. Как пример, определить существует ли файл или нет, и в зависимости от этого предпринять какие-то действия.

If…then…else…fi синтаксис:

if [ условие ]
then
 если условие справедливо
 выполнить все команды до else или
 до fi
else
 если условие не справедливо
 выполнить все команды до fi
fi

Очень важно запомнить, ваша конструкция должна всегда заканчиваться на словом fi!

Выражения используемые с if

В приведенной внизу таблице содержаться операторы которые выполняют команду test или набор команд. Эти операторы заключаются в квадратные скобки [] для проверки выполнения условия.

[ -a FILE ] Правда елси FILE существует.
[ -b FILE ] Правда елси FILE существует и это специальный блоковый файл.
[ -c FILE ] Правда елси FILE существует и это специальный знаковый файл.
[ -d FILE ] Правда елси FILE существует и это директория.
[ -e FILE ] Правда елси FILE существует.
[ -f FILE ] Правда елси FILE существует и это регулярный файл.
[ -g FILE ] Правда елси FILE существует и установлен SGID бит.
[ -h FILE ] Правда елси FILE существует и это символический ссылка.
[ -k FILE ] Правда елси FILE существует и второй промежуточный бит округления установлен.
[ -p FILE ] Правда елси FILE существует и это named pipe (FIFO).
[ -r FILE ] Правда елси FILE существует и он доступен на чтение.
[ -s FILE ] Правда елси FILE существует и больше нуля.
[ -u FILE ] Правда елси FILE существует и SUID (set user ID) бит установлен.
[ -w FILE ] Правда елси FILE существует и он доступен на запись.
[ -x FILE ] Правда елси FILE существует и он доступен на исполнение.
[ -O FILE ] Правда елси FILE существует принадлежит существующему пользователю
[ -G FILE ] Правда елси FILE существует принадлежит существующей группе.
[ -L FILE ] Правда елси FILE существует и это символический ссылка.
[ -N FILE ] Правда елси FILE существует и был изменен с тех пор как был прочитан.
[ -S FILE ] Правда елси FILE существует и это сокет.
[ FILE1 -nt FILE2 ] Правда, если файл FILE1 изменялся чаще чем FILE2, или есои FILE1 существует, а FILE2 нет.
[ FILE1 -ot FILE2 ] Правда, если файл FILE1 старше чем FILE2, или FILE1 существует, а FILE2 нет.
[ FILE1 -ef FILE2 ] Правда, если FILE1 и FILE2 относятся к одному устройству и номеру инода.
[ -o OPTIONNAME ] Правда если shell опция "OPTIONNAME" включена.
[ -z STRING ] Правда если длинна "STRING" равна 0.
[ -n STRING ] or [ STRING ] Правда если длинна "STRING" не равна 0.
[ STRING1 == STRING2 ] Правда если выражения эквивалентны. 
[ STRING1 != STRING2 ] Правда если выражения не эквивалентны.
[ STRING1 < STRING2 ] Правда если "STRING1" лексикографически упорядоченно до "STRING2".
[ STRING1 > STRING2 ] Правда если "STRING1" лексикографически упорядоченно после "STRING2".
[ ARG1 OP ARG2 ] "OP" это один из следующих параметров -eq, -ne, -lt, -le, -gt or -ge. Эти бинарные арифметические 
операторы возвращают результат "правда" если "ARG1" эквивалентен(-eq), не эквивалентен(-ne), меньше чем(-lt), 
меньше или эквивалентен(-le), больше чем(-gt), больше или эквивалентно(-ge) к "ARG2".  
[ ! EXPR ] правда если выражение EXPR не справедливо.
[ ( EXPR ) ] возвращает значение EXPR. Это может быть использовано для изменения приоритета операторов.
[ EXPR1 -a EXPR2 ] правда, если оба выражения EXPR1 и EXPR2 справедливы.
[ EXPR1 -o EXPR2 ] правда, если хотя бы одно выражение EXPR1 или EXPR2 справедливы.

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

#!/bin/bash
read -p "Введите число : " n
if [ $n -ge 0 ];
then
	echo "$n положительное число."
else
	echo "$n отрицательное число."
fi

другой пример, определим, существует ли введенный нами пользователь:

#!/bin/bash
read -p "Введите имя пользователя : " USER
if ! grep $USER /etc/passwd
then
	echo "$n не существует."
else
	echo "$n существует."
fi

Восклицательный знак перед grep $USER /etc/passwd, говорит о том, что условие выполниться если пользователя не существует. А теперь давайте перепишем этот скрипт только используя специальный параметр $? который мы рассматривали в третем уроке:

#!/bin/bash
read -p "Введите имя пользователя : " USER
grep $USER /etc/passwd
if [ $? -ne 0 ]; 
then
	echo "$n не существует."
else
	echo "$n существует."
fi

Пример использование сравнения строк. скрипт будет проверять root вы или нет:

#!/bin/bash
if [ "$(whoami)" != 'root' ]; then
        echo "У вас нет прав для запуска $0."
        exit 1;
fi

данный скрипт можно переписать короче:

#!/bin/bash
[ "$(whoami)" != 'root' ] && ( echo У вас нет прав для запуска; exit 1 )

Вы так же можете использовать регулярные выражения. Как пример. пускай наш скрипт определяет содержит ли введенный нам текст букву «ч»:

#!/bin/bash
LATTER="ч"
read -p "Введите предложение : " STR
if [[ "$STR" == *$LATTER* ]]; 
then
	echo "$LATTER найдено."
else
	echo "$LATTER не найдено."
fi

Несколько слов по поводу использования двойных и одинарных квадратных скобок. При использовании двойных скобок ваши переменный не будут разбиты на несколько отдельных слов если вы использовали пробел, как пример, переменная VAR=»var with space» будет единым целым.

Часть 1: скрипт Hellow World
Часть 2: Переменные
Часть 3: Специальные параметры
Часть 4: Одинарные и двойные кавычки. Математические операции
Часть 5: Структурные конструкции и команда test
Часть 6: Структура If…then…else
Часть 7: Подмножества и части строк. Размеры