Linux присвоить вывод команды переменной

Основы BASH. Часть 2

Эта часть посвящена циклам, математическим операциям и использованию внешних команд.

Циклы. Цикл for-in

Оператор for-in предназначен для поочередного обращения к значениям перечисленным в списке. Каждое значение поочередно в списке присваивается переменной. Синтаксис следующий:

for переменная in список_значений do команды done

Рассмотрим небольшой пример:

#!/bin/bash for i in 0 1 2 3 4 #переменной $i будем поочередно присваивать значения от 0 до 4 включительно do echo "Console number is $i" >> /dev/pts/$i #Пишем в файл /dev/pts/$i(файл виртуального терминала) строку "Console number is $i" done #цикл окончен exit 0

После выполнения примера в первых 5 виртуальных консолях (терминалах) появится строка с её номером. В переменную $i поочередно подставляются значения из списка и в цикле идет работа со значением этой переменной.

Циклы. Цикл while

Цикл while сложнее цикла for-in и используется для повторения команд, пока какое-то выражение истинно( код возврата = 0). Синтаксис оператора следующий:

while выражение или команда возвращающая код возврата do команды done

Пример работы цикла рассмотрим на следующем примере:

#!/bin/bash again=yes #присваиваем значение "yes" переменной again while [ "$again" = "yes" ] #Будем выполнять цикл, пока $again будет равно "yes" do echo "Please enter a name:" read name echo "The name you entered is $name" echo "Do you wish to continue?" read again done echo "Bye-Bye"

А теперь результат работы скрипта:

ite@ite-desktop:~$ ./bash2_primer1.sh Please enter a name: ite The name you entered is ite Do you wish to continue? yes Please enter a name: mihail The name you entered is mihail Do you wish to continue? no Bye-Bye

Как видим цикл выполняется до тех пор, пока мы не введем что-то отличное от «yes». Между do и done можно описывать любые структуры, операторы и т.п., все они будут выполнятся в цикле.Но следует быть осторожным с этим циклом, если вы запустите на выполнение в нём какую-либо команду, без изменения переменной выражения, вы можете попасть в бесконечный цикл.

Теперь об условии истинности. После while, как и в условном операторе if-then-else можно вставлять любое выражение или команду, которая возвращает код возврата, и цикл будет исполнятся до тех пор, пока код возврата = 0! Оператор »[» аналог команды test, которая проверяет истинность условия, которое ей передали.

Рассмотрим еще один пример, я взял его из книги Advanced Bash scripting. Уж очень он мне понравился Улыбка, но я его немного упростил. В этом примере мы познакомимся с еще одним типом циклов UNTIL-DO. Эта практически полный аналог цикла WHILE-DO, только выполняется пока какое-то выражение ложно.

#!/bin/bash echo "Введите числитель: " read dividend echo "Введите знаменатель: " read divisor dnd=$dividend #мы будем изменять переменные dividend и divisor, #сохраним их знания в других переменных, т.к. они нам #понадобятся dvs=$divisor remainder=1 until [ "$remainder" -eq 0 ] do let "remainder = dividend % divisor" dividend=$divisor divisor=$remainder done echo "НОД чисел $dnd и $dvs = $dividend"

Результат выполнения скрипта:

ite@ite-desktop:~$ ./bash2_primer3.sh Введите числитель: 100 Введите знаменатель: 90 НОД чисел 100 и 90 = 10

Математические операции

Команда let производит арифметические операции над числами и переменными.

Читайте также:  Network unreachable error in linux

Рассмотрим небольшой пример, в котором мы производим некоторые вычисления над введенными числами:

#!/bin/bash echo "Введите a: " read a echo "Введите b: " read b let "c = a + b" #сложение echo "a+b= $c" let "c = a / b" #деление echo "a/b= $c" let "c #сдвигает c на 2 разряда влево echo "c после сдвига на 2 разряда: $c" let "c = a % b" # находит остаток от деления a на b echo "$a / $b. остаток: $c "
ite@ite-desktop:~$ ./bash2_primer2.sh Введите a: 123 Введите b: 12 a+b= 135 a/b= 10 c после сдвига на 2 разряда: 40 123 / 12. остаток: 3

Ну вот, как видите ничего сложного, список математических операций стандартный:

+ — сложение
— — вычитание
* — умножение
/ — деление
** — возведение в степень
% — модуль(деление по модулю), остаток от деления

let позволяет использовать сокращения арифметических команд, тем самым сокращая кол-во используемых переменных.

Например: a = a+b эквивалентно a +=b и т.д.

Работа с внешними программами при написании shell-скриптов

Для начала немного полезной теории.

Перенаправление потоков

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

stdout — Стандартный вывод. Сюда попадает все что выводят программы
stdin — Стандартный ввод. Это все что набирает юзер в консоли
stderr — Стандартный вывод ошибок.

Для операций с этими дескрипторами, существуют специальные символы: > (перенаправление вывода), < (перенаправление ввода). Оперировать ими не сложно. Например:

перенаправить вывод команды cat /dev/random в /dev/null (абсолютно бесполезная операция ) или

записать в файл listing содержание текущего каталога (уже полезней)

Если есть необходимость дописывать в файл (при использовании »>» он заменяется), необходимо вместо »>» использовать »>>»

после просьбы sudo ввести пароль, он возьмется из файла my_password, как будто вы его ввели с клавиатуры.

Если необходимо записать в файл только ошибки, которые могли возникнуть при работе программы, то можно использовать:

./program_with_error 2> error_file

цифра 2 перед »>» означает что нужно перенаправлять все что попадет в дескриптор 2(stderr).

Если необходимо заставить stderr писать в stdout, то это можно можно след. образом:

символ »&» означает указатель на дескриптор 1(stdout)

(По умолчанию stderr пишет на ту консоль, в которой работает пользователь (вернее пишет на дисплей)).

2. Конвейеры

Конвейер — очень мощный инструмент для работы с консолью Bash. Синтаксис простой:

команда1 | команда 2 — означает, что вывод команды 1 передастся на ввод команде 2

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

ls -la | grep "hash" |sort > sortilg_list

вывод команды ls -la передается команде grep, которая отбирает все строки, в которых встретится слово hash, и передает команде сортировке sort, которая пишет результат в файл sorting_list. Все довольно понятно и просто.

Чаще всего скрипты на Bash используются в качестве автоматизации каких-то рутинных операций в консоли, отсюда иногда возникает необходимость в обработке stdout одной команды и передача на stdin другой команде, при этом результат выполнения одной команды должен быть неким образом обработан. В этом разделе я постараюсь объяснить основные принципы работы с внешними командами внутри скрипта. Думаю что примеров я привел достаточно и можно теперь писать только основные моменты.

1. Передача вывода в переменную

Для того чтобы записать в переменную вывод какой-либо команды, достаточно заключить команду в « кавычки, например

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

LIST=`find /svn/ -type d 2>/dev/null| awk ' '| sort|uniq | tr '\n' ' '` for ONE_OF_LIST in $LIST do svnadmin hotcopy /svn/$ONE_OF_LIST /svn/temp4backup/$ONE_OF_LIST done

Здесь мы используем цикл for-do-done для архивирование всех директорий в папке /svn/ с помощью команды svnadmin hotcopy(что в нашем случае не имеет никого значения, просто как пример). Наибольшй интерес вызывает строка: LIST=`find /svn/ -type d 2>/dev/null| awk ‘ ‘| sort|uniq | tr ‘\n’ ‘ ‘` В ней переменной LIST присваивается выполнение команды find, обработанной командами awk, sort, uniq,tr(все эти команды мы рассматривать не будем, ибо это отдельная статья). В переменной LIST будут имена всех каталогов в папке /svn/ пгомещенных в одну строку(для того чтобы её стравить циклу.

Как видно, все не сложно, достаточно понять принцип и написать пару своих скриптов. В заключении статьи хочу пожелать удачи в изучении BASH и Linux в целом. Критика, как водится приветствуется. Следующая статья возможно будет посвящена использованию таких программ как sed, awk.

Автор: Zloy_T

Источник

Сохранить результат команды в переменную

У меня создание переменной LINEFIO=$($|iconv -f ‘windows-1251’ -t ‘UTF-8′) заканчивается сообщением line 282: $’\317\340\342\353\376\352\345\342\350\367’: команда не найдена хотя просто echo «$|iconv -f ‘windows-1251’ -t ‘UTF-8′» проходит на ура, в чем дело ? L

test=$(curl -I ya.ru) % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 —:—:— —:—:— —:—:— 0

@HelloKatty curl выводит в STDERR прогресс загрузки. Это не попадает в переменную. Рабочий пример: TEST=$(curl https://ya.ru) Теперь в переменной $TEST находится куча HTML: echo $TEST

Команду в обратные апострофы:

RESULT=`ibus engine` echo $RESULT 
$ engine="ibus engine" $ $engine xkb:ru::rus 

@dimka3210, объясните, пожалуйста зачем в начале каждой строки доллар. Где можно почитать про это? У меня так не работает

Но это вы просто записали команду в переменную, а как мне записать результат команды, то есть xkb:ru::rus. Чтоб при echo «$engine» выдавало «xkb:ru::rus»?

Это то что я искал. Огромное спасибо! По незнаю допустил эту ошибку (только учусь) и не мог понять почему же у меня не работает переменная, почему не сравнивает. Было

и ещё несколько разных вариантов. Когда стало по примеру ниже — у меня всё заработало как нужно и я наконец-то приблизился к завершению своего скрипта. Всем успехов!

Источник

How do I redirect output to a variable in shell? [duplicate]

I want to get stream generated by genhash in a variable. How do I redirect it into a variable $hash to compare inside a conditional?

if [ $hash -ne 0 ] then echo KO exit 0 else echo -n OK exit 0 fi 

This question is the older than the linked answer. Therefore the linked answer is the duplicate, and should be marked as «asked before», not this one.

Bash and Shell are different things, hence it’s no duplicate. Shell doesn’t support all of bash’s features.

8 Answers 8

hash=$(genhash --use-ssl -s $IP -p 443 --url $URL | grep MD5 | grep -c $MD5) 

This captures the output of a command, but it does not use a redirect. If you actually need to use a redirect because of a more complex need, See my answer. Google brought you here, right? Why go somewhere else to find the answer you searched for?

@Kayvar when you use $( . ) it uses new subshell, so the result of command can be not the same as in the primary shell

It would be helpful to others if you made it clear whether this only captures STDOUT or if it also captures STDERR. It would also be very helpful if you could show how to print the exit code of the command inside $(. )

But, because pipes create forks, you have to use $foo before the pipe ends, so.

echo "abc" | ( read foo; date +"I received $foo on %D"; ) 

Sure, all these other answers show ways to not do what the OP asked, but that really screws up the rest of us who searched for the OP’s question.

The answer to the question is to use the read command.

Here’s how you do it

# I would usually do this on one line, but for readability. series | of | commands \ | \ ( read string; mystic_command --opt "$string" /path/to/file ) \ | \ handle_mystified_file 

Here is what it is doing and why it is important:

  1. Let’s pretend that the series | of | commands is a very complicated series of piped commands.
  2. mystic_command can accept the content of a file as stdin in lieu of a file path, but not the —opt arg therefore it must come in as a variable. The command outputs the modified content and would commonly be redirected into a file or piped to another command. (E.g. sed , awk , perl , etc.)
  3. read takes stdin and places it into the variable $string
  4. Putting the read and the mystic_command into a «sub shell» via parenthesis is not necessary but makes it flow like a continuous pipe as if the 2 commands where in a separate script file.

There is always an alternative, and in this case the alternative is ugly and unreadable compared to my example above.

# my example above as a oneliner series | of | commands | (read string; mystic_command --opt "$string" /path/to/file) | handle_mystified_file # ugly and unreadable alternative mystic_command --opt "$(series | of | commands)" /path/to/file | handle_mystified_file 

My way is entirely chronological and logical. The alternative starts with the 4th command and shoves commands 1, 2, and 3 into command substitution.

I have a real world example of this in this script but I didn’t use it as the example above because it has some other crazy/confusing/distracting bash magic going on also.

Источник

Оцените статью
Adblock
detector