Результат выполнения команды в переменную bash: ввод и вывод / Блог компании RUVDS.com / Хабр
ввод и вывод / Блог компании RUVDS.com / Хабр
Bash-скрипты: начало
Bash-скрипты, часть 2: циклы
Bash-скрипты, часть 3: параметры и ключи командной строки
Bash-скрипты, часть 4: ввод и вывод
Bash-скрипты, часть 5: сигналы, фоновые задачи, управление сценариями
Bash-скрипты, часть 6: функции и разработка библиотек
Bash-скрипты, часть 7: sed и обработка текстов
Bash-скрипты, часть 8: язык обработки данных awk
Bash-скрипты, часть 9: регулярные выражения
Bash-скрипты, часть 10: практические примеры
Bash-скрипты, часть 11: expect и автоматизация интерактивных утилит
В прошлый раз, в третьей части этой серии материалов по bash-скриптам, мы говорили о параметрах командной строки и ключах. Наша сегодняшняя тема — ввод, вывод, и всё, что с этим связано.
Вы уже знакомы с двумя методами работы с тем, что выводят сценарии командной строки:
- Отображение выводимых данных на экране.
- Перенаправление вывода в файл.
Иногда что-то надо показать на экране, а что-то — записать в файл, поэтому нужно разобраться с тем, как в Linux обрабатывается ввод и вывод, а значит — научиться отправлять результаты работы сценариев туда, куда нужно. Начнём с разговора о стандартных дескрипторах файлов.
Стандартные дескрипторы файлов
Всё в Linux — это файлы, в том числе — ввод и вывод. Операционная система идентифицирует файлы с использованием дескрипторов.
Каждому процессу позволено иметь до девяти открытых дескрипторов файлов. Оболочка bash резервирует первые три дескриптора с идентификаторами 0, 1 и 2. Вот что они означают.
0
,STDIN —
стандартный поток ввода.1
,STDOUT —
стандартный поток вывода.2
,STDERR —
стандартный поток ошибок.
Эти три специальных дескриптора обрабатывают ввод и вывод данных в сценарии.
Вам нужно как следует разобраться в стандартных потоках. Их можно сравнить с фундаментом, на котором строится взаимодействие скриптов с внешним миром. Рассмотрим подробности о них.
STDIN
STDIN —
это стандартный поток ввода оболочки. Для терминала стандартный ввод — это клавиатура. Когда в сценариях используют символ перенаправления ввода — <
, Linux заменяет дескриптор файла стандартного ввода на тот, который указан в команде. Система читает файл и обрабатывает данные так, будто они введены с клавиатуры.
Многие команды bash принимают ввод из STDIN
, если в командной строке не указан файл, из которого надо брать данные. Например, это справедливо для команды cat
.
Когда вы вводите команду cat
в командной строке, не задавая параметров, она принимает ввод из STDIN
. После того, как вы вводите очередную строку, cat
просто выводит её на экран.
STDOUT
STDOUT —
стандартный поток вывода оболочки. По умолчанию это — экран. Большинство bash-команд выводят данные в STDOUT
, что приводит к их появлению в консоли. Данные можно перенаправить в файл, присоединяя их к его содержимому, для этого служит команда >>
.
Итак, у нас есть некий файл с данными, к которому мы можем добавить другие данные с помощью этой команды:
pwd >> myfile
То, что выведет pwd
, будет добавлено к файлу myfile
, при этом уже имеющиеся в нём данные никуда не денутся.
Перенаправление вывода команды в файл
Пока всё хорошо, но что если попытаться выполнить что-то вроде показанного ниже, обратившись к несуществующему файлу xfile
, задумывая всё это для того, чтобы в файл myfile
попало сообщение об ошибке.
ls –l xfile > myfile
После выполнения этой команды мы увидим сообщения об ошибках на экране.
Попытка обращения к несуществующему файлу
При попытке обращения к несуществующему файлу генерируется ошибка, но оболочка не перенаправила сообщения об ошибках в файл, выведя их на экран. Но мы-то хотели, чтобы сообщения об ошибках попали в файл. Что делать? Ответ прост — воспользоваться третьим стандартным дескриптором.
STDERR
STDERR
представляет собой стандартный поток ошибок оболочки. По умолчанию этот дескриптор указывает на то же самое, на что указывает STDOUT
, именно поэтому при возникновении ошибки мы видим сообщение на экране.
Итак, предположим, что надо перенаправить сообщения об ошибках, скажем, в лог-файл, или куда-нибудь ещё, вместо того, чтобы выводить их на экран.
▍Перенаправление потока ошибок
Как вы уже знаете, дескриптор файла STDERR —
2. Мы можем перенаправить ошибки, разместив этот дескриптор перед командой перенаправления:
ls -l xfile 2>myfile
cat ./myfile
Сообщение об ошибке теперь попадёт в файл myfile
.
Перенаправление сообщения об ошибке в файл
▍Перенаправление потоков ошибок и вывода
При написании сценариев командной строки может возникнуть ситуация, когда нужно организовать и перенаправление сообщений об ошибках, и перенаправление стандартного вывода. Для того, чтобы этого добиться, нужно использовать команды перенаправления для соответствующих дескрипторов с указанием файлов, куда должны попадать ошибки и стандартный вывод:
ls –l myfile xfile anotherfile 2> errorcontent 1> correctcontent
Перенаправление ошибок и стандартного вывода
Оболочка перенаправит то, что команда ls
обычно отправляет в STDOUT
, в файл correctcontent
благодаря конструкции 1>
. Сообщения об ошибках, которые попали бы в STDERR
, оказываются в файле errorcontent
из-за команды перенаправления 2>
.
Если надо, и STDERR
, и STDOUT
можно перенаправить в один и тот же файл, воспользовавшись командой &>
:
Перенаправление STDERR и STDOUT в один и тот же файл
После выполнения команды то, что предназначено для STDERR
и STDOUT
, оказывается в файле content
.
Перенаправление вывода в скриптах
Существует два метода перенаправления вывода в сценариях командной строки:
- Временное перенаправление, или перенаправление вывода одной строки.
- Постоянное перенаправление, или перенаправление всего вывода в скрипте либо в какой-то его части.
▍Временное перенаправление вывода
В скрипте можно перенаправить вывод отдельной строки в STDERR
. Для того, чтобы это сделать, достаточно использовать команду перенаправления, указав дескриптор STDERR
, при этом перед номером дескриптора надо поставить символ амперсанда (&
):
#!/bin/bash
echo "This is an error" >&2
echo "This is normal output"
Если запустить скрипт, обе строки попадут на экран, так как, как вы уже знаете, по умолчанию ошибки выводятся туда же, куда и обычные данные.
Временное перенаправление
Запустим скрипт так, чтобы вывод STDERR
попадал в файл.
./myscript 2> myfile
Как видно, теперь обычный вывод делается в консоль, а сообщения об ошибках попадают в файл.
Сообщения об ошибках записываются в файл
▍Постоянное перенаправление вывода
Если в скрипте нужно перенаправлять много выводимых на экран данных, добавлять соответствующую команду к каждому вызову echo
неудобно. Вместо этого можно задать перенаправление вывода в определённый дескриптор на время выполнения скрипта, воспользовавшись командой exec
:
#!/bin/bash
exec 1>outfile
echo "This is a test of redirecting all output"
echo "from a shell script to another file."
echo "without having to redirect every line"
Запустим скрипт.
Перенаправление всего вывода в файл
Если просмотреть файл, указанный в команде перенаправления вывода, окажется, что всё, что выводилось командами echo
, попало в этот файл.
Команду exec
можно использовать не только в начале скрипта, но и в других местах:
#!/bin/bash
exec 2>myerror
echo "This is the start of the script"
echo "now redirecting all output to another location"
exec 1>myfile
echo "This should go to the myfile file"
echo "and this should go to the myerror file" >&2
Вот что получится после запуска скрипта и просмотра файлов, в которые мы перенаправляли вывод.
Перенаправление вывода в разные файлы
Сначала команда exec
задаёт перенаправление вывода из STDERR
в файл myerror
. Затем вывод нескольких команд echo
отправляется в STDOUT
и выводится на экран. После этого команда exec
задаёт отправку того, что попадает в STDOUT
, в файл myfile
, и, наконец, мы пользуемся командой перенаправления в STDERR
в команде echo
, что приводит к записи соответствующей строки в файл myerror.
Освоив это, вы сможете перенаправлять вывод туда, куда нужно. Теперь поговорим о перенаправлении ввода.
Перенаправление ввода в скриптах
Для перенаправления ввода можно воспользоваться той же методикой, которую мы применяли для перенаправления вывода. Например, команда exec
позволяет сделать источником данных для STDIN
какой-нибудь файл:
exec 0< myfile
Эта команда указывает оболочке на то, что источником вводимых данных должен стать файл myfile
, а не обычный STDIN
. Посмотрим на перенаправление ввода в действии:
#!/bin/bash
exec 0< testfile
count=1
while read line
do
echo "Line #$count: $line"
count=$(( $count + 1 ))
done
Вот что появится на экране после запуска скрипта.
Перенаправление ввода
В одном из предыдущих материалов вы узнали о том, как использовать команду read
для чтения данных, вводимых пользователем с клавиатуры. Если перенаправить ввод, сделав источником данных файл, то команда read
, при попытке прочитать данные из STDIN
, будет читать их из файла, а не с клавиатуры.
Некоторые администраторы Linux используют этот подход для чтения и последующей обработки лог-файлов.
Создание собственного перенаправления вывода
Перенаправляя ввод и вывод в сценариях, вы не ограничены тремя стандартными дескрипторами файлов. Как уже говорилось, можно иметь до девяти открытых дескрипторов. Остальные шесть, с номерами от 3 до 8, можно использовать для перенаправления ввода или вывода. Любой из них можно назначить файлу и использовать в коде скрипта.
Назначить дескриптор для вывода данных можно, используя команду exec
:
#!/bin/bash
exec 3>myfile
echo "This should display on the screen"
echo "and this should be stored in the file" >&3
echo "And this should be back on the screen"
После запуска скрипта часть вывода попадёт на экран, часть — в файл с дескриптором 3
.
Перенаправление вывода, используя собственный дескриптор
Создание дескрипторов файлов для ввода данных
Перенаправить ввод в скрипте можно точно так же, как и вывод. Сохраните STDIN
в другом дескрипторе, прежде чем перенаправлять ввод данных.
После окончания чтения файла можно восстановить STDIN
и пользоваться им как обычно:
#!/bin/bash
exec 6<&0
exec 0< myfile
count=1
while read line
do
echo "Line #$count: $line"
count=$(( $count + 1 ))
done
exec 0<&6
read -p "Are you done now? " answer
case $answer in
y) echo "Goodbye";;
n) echo "Sorry, this is the end.";;
esac
Испытаем сценарий.
Перенаправление ввода
В этом примере дескриптор файла 6 использовался для хранения ссылки на STDIN
. Затем было сделано перенаправление ввода, источником данных для STDIN
стал файл. После этого входные данные для команды read
поступали из перенаправленного STDIN
, то есть из файла.
После чтения файла мы возвращаем STDIN
в исходное состояние, перенаправляя его в дескриптор 6
. Теперь, для того, чтобы проверить, что всё работает правильно, скрипт задаёт пользователю вопрос, ожидает ввода с клавиатуры и обрабатывает то, что введено.
Закрытие дескрипторов файлов
Оболочка автоматически закрывает дескрипторы файлов после завершения работы скрипта. Однако, в некоторых случаях нужно закрывать дескрипторы вручную, до того, как скрипт закончит работу. Для того, чтобы закрыть дескриптор, его нужно перенаправить в &-
. Выглядит это так:
#!/bin/bash
exec 3> myfile
echo "This is a test line of data" >&3
exec 3>&-
echo "This won't work" >&3
После исполнения скрипта мы получим сообщение об ошибке.
Попытка обращения к закрытому дескриптору файла
Всё дело в том, что мы попытались обратиться к несуществующему дескриптору.
Будьте внимательны, закрывая дескрипторы файлов в сценариях. Если вы отправляли данные в файл, потом закрыли дескриптор, потом — открыли снова, оболочка заменит существующий файл новым. То есть всё то, что было записано в этот файл ранее, будет утеряно.
Получение сведений об открытых дескрипторах
Для того, чтобы получить список всех открытых в Linux дескрипторов, можно воспользоваться командой lsof
. Во многих дистрибутивах, вроде Fedora, утилита lsof
находится в /usr/sbin
. Эта команда весьма полезна, так как она выводит сведения о каждом дескрипторе, открытом в системе. Сюда входит и то, что открыли процессы, выполняемые в фоне, и то, что открыто пользователями, вошедшими в систему.
У этой команды есть множество ключей, рассмотрим самые важные.
-p
Позволяет указатьID
процесса.-d
Позволяет указать номер дескриптора, о котором надо получить сведения.
Для того, чтобы узнать PID
текущего процесса, можно использовать специальную переменную окружения $$
, в которую оболочка записывает текущий PID
.
Ключ -a
используется для выполнения операции логического И
над результатами, возвращёнными благодаря использованию двух других ключей:
lsof -a -p $$ -d 0,1,2
Вывод сведений об открытых дескрипторах
Тип файлов, связанных с STDIN
, STDOUT
и STDERR —
CHR (character mode, символьный режим). Так как все они указывают на терминал, имя файла соответствует имени устройства, назначенного терминалу. Все три стандартных файла доступны и для чтения, и для записи.
Посмотрим на вызов команды lsof
из скрипта, в котором открыты, в дополнение к стандартным, другие дескрипторы:
#!/bin/bash
exec 3> myfile1
exec 6> myfile2
exec 7< myfile3
lsof -a -p $$ -d 0,1,2,3,6,7
Вот что получится, если этот скрипт запустить.
Просмотр дескрипторов файлов, открытых скриптом
Скрипт открыл два дескриптора для вывода (3
и 6
) и один — для ввода (7
). Тут же показаны и пути к файлам, использованных для настройки дескрипторов.
Подавление вывода
Иногда надо сделать так, чтобы команды в скрипте, который, например, может исполняться как фоновый процесс, ничего не выводили на экран. Для этого можно перенаправить вывод в /dev/null
. Это — что-то вроде «чёрной дыры».
Вот, например, как подавить вывод сообщений об ошибках:
ls -al badfile anotherfile 2> /dev/null
Тот же подход используется, если, например, надо очистить файл, не удаляя его:
cat /dev/null > myfile
Итоги
Сегодня вы узнали о том, как в сценариях командной строки работают ввод и вывод. Теперь вы умеете обращаться с дескрипторами файлов, создавать, просматривать и закрывать их, знаете о перенаправлении потоков ввода, вывода и ошибок. Всё это очень важно в деле разработки bash-скриптов.
В следующий раз поговорим о сигналах Linux, о том, как обрабатывать их в сценариях, о запуске заданий по расписанию и о фоновых задачах.
Уважаемые читатели! В этом материале даны основы работы с потоками ввода, вывода и ошибок. Уверены, среди вас есть профессионалы, которые могут рассказать обо всём этом то, что приходит лишь с опытом. Если так — передаём слово вам.
bash-автоматический захват вывода последней выполненной команды в переменную
Я хотел бы иметь возможность использовать результат последней выполненной команды в последующей команде. Например,
$ find . -name foo.txt
./home/user/some/directory/foo.txt
теперь предположим, что я хочу иметь возможность открыть файл в редакторе, или удалить его, или сделать что-то еще с ним, например
mv <some-variable-that-contains-the-result> /some/new/location
как я могу это сделать? Может быть, используя некоторую переменную bash?
обновление:
чтобы уточнить, я не хочу назначать вещи вручную. То, что мне нужно, — это что-то вроде встроенного bash переменные, например,
ls /tmp
cd $_
$_
содержит последний аргумент предыдущей команды. Я хочу что-то подобное, но с выходом последней команды.
последнее обновление:
ответ сета сработал довольно хорошо. Пару вещей, чтобы иметь в виду:
- не забудьте
touch /tmp/x
при попытке решения в первый раз - результат будет сохранен только в том случае, если код выхода последней команды был успешный
128
автор: armandino
20 ответов
это действительно хакерское решение, но, похоже, в основном работает некоторое время. Во время тестирования я отметил, что иногда это не очень хорошо работает при получении ^C в командной строке, хотя я немного подправил его, чтобы вести себя немного лучше.
этот хак является интерактивным режимом Хак только, и я уверен, что я бы не рекомендовал его никому. Фоновые команды, вероятно, вызовут еще менее определенное поведение, чем обычно. Другие ответы лучше способ программного получения результатов.
Это, как говорится, вот такое «решение»:
PROMPT_COMMAND='LAST="`cat /tmp/x`"; exec >/dev/tty; exec > >(tee /tmp/x)'
установите эту переменную окружающей среды bash и выдает команды по желанию. $LAST
обычно будет иметь выход, который вы ищете:
startide seth> fortune
Courtship to marriage, as a very witty prologue to a very dull play.
-- William Congreve
startide seth> echo "$LAST"
Courtship to marriage, as a very witty prologue to a very dull play.
-- William Congreve
66
автор: Seth Robertson
Я не знаю ни одной переменной, которая делает это автоматически. Делать что-то помимо просто копирования вставки результата, вы можете повторно запустить все, что вы только что сделали, например
vim $(!!)
здесь !!
расширение истории означает «предыдущая команда».
Если вы ожидаете, что в нем будет одно имя файла с пробелами или другими символами, которые могут помешать правильному анализу аргументов, укажите результат (vim "$(!!)"
). Оставляя его без кавычек, позволит нескольким файлам открываться сразу, если они не включают пробелы или другие маркеры синтаксического анализа оболочки.
Баш — это своего рода уродливый язык. Да, вы можете назначить выход переменной
MY_VAR="$(find -name foo.txt)"
echo "$MY_VAR"
но лучше надеяться, что ваш трудный что find
возвращен только один результат, и в этом результате не было никаких «нечетных» символов, таких как возврат каретки или фиды строк, поскольку они будут молча изменены при назначении переменной Bash.
но лучше быть осторожным, чтобы правильно процитировать переменную при ее использовании!
лучше действовать на файл напрямую, например, с find
‘ s -execdir
(обратитесь к руководству).
find -name foo.txt -execdir vim '{}' ';'
или
find -name foo.txt -execdir rename 's/\.txt$/.xml/' '{}' ';'
есть несколько способов сделать это. Один из способов-использовать v=$(command)
, который назначит вывод команды v
. Например:
v=$(date)
echo $v
и вы можете тоже использовать обратных кавычек
v=`date`
echo $v
С Bash Руководство Для Начинающих,
когда старого стиля backquoted форма замещения используется обратная косая черта сохраняет свой буквальный смысл, за исключением, когда вслед за»$», » ` » или «\». Первые обратные палочки, которым не предшествует обратная косая черта завершает команду. При использовании формы «$(COMMAND) » все символы между скобками составляют команду; ни один из них не обрабатывается специально.
EDIT: после редактирования в вопросе кажется, что это не то, что ищет OP. Насколько я знаю, нет специальной переменной типа $_
для вывода последней команды.
Это довольно легко. Используйте back-quotes:
var=`find . -name foo.txt`
и затем вы можете использовать это в любое время в будущем
echo $var
mv $var /somewhere
9
автор: Wes Hardaker
Я думаю, вы могли бы взломать решение, которое включает в себя установку вашей оболочки на скрипт, содержащий:
#!/bin/sh
bash | tee /var/log/bash.out.log
потом, если вы установите $PROMPT_COMMAND
чтобы вывести разделитель, вы можете написать вспомогательную функцию (возможно, называемую _
) это дает вам последний кусок этого журнала, поэтому вы можете использовать его как:
% find lots*of*files
...
% echo "$(_)"
... # same output, but doesn't run the command again
9
автор: Jay Adkisson
Disclamers:
- этот ответ запаздывает на полгода: D
- Я тяжелый пользователь tmux
- вы должны запустить свою оболочку в tmux, чтобы это работало
при запуске интерактивной оболочки в tmux вы можете легко получить доступ к данным, отображаемым в настоящее время на терминале. Давайте посмотрим на некоторые интересные команды:
- захват-панели tmux: этот копирует отображаемые данные в один из tmux внутренний буфер. Он может скопировать историю, которая в настоящее время не видна, но мы не заинтересованы в этом сейчас
- список tmux-буферы: здесь отображается информация о захваченных буферов. Самый новый будет иметь номер 0.
- tmux show-buffer-b (буфер num): это печатает содержимое данного буфера терминала
- tmux paste-buffer-b (буфер num): это вставляет содержимое данного буфера ввод
Да, это дает нам много возможностей сейчас 🙂 Что касается меня, я установил простой псевдоним:alias L="tmux capture-pane; tmux showb -b 0 | tail -n 3 | head -n 1"
и теперь каждый раз, когда мне нужно получить доступ к последней строке я просто использовать $(L)
чтобы получить его.
это не зависит от выходного потока, используемого программой (будь то stdin или stderr), метода печати (ncurses и т. д.) и код выхода программы — данные просто должны быть отображены.
8
автор: Wiesław Herr
вы можете настроить следующий псевдоним в своем профиле bash:
alias s='it=$($(history | tail -2 | head -1 | cut -d" " -f4-))'
затем, введя » s «после произвольной команды, вы можете сохранить результат в переменную оболочки «it».
вот пример использования такой:
$ which python
/usr/bin/python
$ s
$ file $it
/usr/bin/python: symbolic link to `python2.6'
6
автор: Joe Tallett
Я только что дистиллировал это bash
функция из предложений здесь:
grab() {
grab=$("$@")
echo $grab
}
тогда вы просто делаете:
> grab date
Do 16. Feb 13:05:04 CET 2012
> echo $grab
Do 16. Feb 13:05:04 CET 2012
обновление: анонимный пользователь предложил заменить echo
by printf '%s\n'
, который имеет то преимущество, что он не обрабатывает параметры, как -e
в схватил текст. Поэтому, если вы ожидаете или испытываете такие особенности, рассмотрите это предложение. Другой вариант-использовать .
6
автор: Tilman Vogel
захват вывода с помощью backticks:
output=`program arguments`
echo $output
emacs $output
обычно я делаю то, что предложили другие… без задания:
$find . -iname '*.cpp' -print
./foo.cpp
./bar.cpp
$vi `!!`
2 files to edit
Вы можете получить fancier, если хотите:
$grep -R "some variable" * | grep -v tags
./foo/bar/xxx
./bar/foo/yyy
$vi `!!`
говоря:» я хотел бы иметь возможность использовать результат последней выполненной команды в последующей команде»,Я предполагаю, вы имеете в виду результат любую команду, не просто найти.
если это так — xargs это то, что вы ищете.
find . -name foo.txt -print0 | xargs -0 -I{} mv {} /some/new/location/{}
или если вы заинтересованы, чтобы увидеть первый выход:
find . -name foo.txt -print0
!! | xargs -0 -I{} mv {} /some/new/location/{}
эта команда имеет дело с несколькими файлами и работает как шарм, даже если путь и/или имя файла содержит пробел(ы).
уведомления mv {} / some/new/location / {} часть команды. Эта команда строится и выполняется для каждой строки, напечатанной предыдущей командой. Здесь строка, напечатанная более ранней командой, заменяется на {}.
выдержка из man-страницы xargs:
xargs-построение и выполнение командных строк из стандартного ввода
Подробнее см. справочная страница:
man xargs
Если все, что вы хотите, это повторить последнюю команду и получить результат, простая переменная bash будет работать:
LAST=`!!`
таким образом, вы можете запустить свою команду на выходе с помощью:
yourCommand $LAST
это породит новый процесс и повторит вашу команду, а затем даст вам результат. Похоже, что вам действительно хотелось бы иметь файл истории bash для вывода команды. Это означает, что вам нужно будет захватить вывод, который bash отправляет на ваш терминал. Вы могли бы написать что-нибудь смотрите /dev или /proc необходимо, но это грязно. Вы также можете просто создать «специальную трубу» между вашим термином и bash с командой tee в середине, которая перенаправляет на ваш выходной файл.
но оба они являются своего рода хакерскими решениями. Я думаю, что лучше всего было бы Терминатор который является более современным терминалом с регистрацией выходных данных. Просто проверьте файл журнала для результатов последней команды. Переменная bash, подобная приведенной выше, сделает это даже упроститься.
2
автор: Spencer Rathbun
вот один из способов сделать это после того, как вы выполнили ваш приказ и решил, что вы хотите сохранить результат в переменной:
$ find . -name foo.txt
./home/user/some/directory/foo.txt
$ OUTPUT=`!!`
$ echo $OUTPUT
./home/user/some/directory/foo.txt
$ mv $OUTPUT somewhere/else/
или если вы заранее знаете, что вам понадобится результат в переменной, вы можете использовать backticks:
$ OUTPUT=`find . -name foo.txt`
$ echo $OUTPUT
./home/user/some/directory/foo.txt
в качестве альтернативы существующим ответам: используйте while
если имена файлов могут содержать пробелы, вот так:
find . -name foo.txt | while IFS= read -r var; do
echo "$var"
done
Как я уже писал, разница имеет значение только если вы должны ожидать пробелы в именах файлов.
NB: единственный встроенный материал-это не о выходе, а о состоянии последней команды.
1
автор: 0xC0000022L
вы можете использовать !!:1. Пример:
~]$ ls *.~
class1.cpp~ class1.h~ main.cpp~ CMakeList.txt~
~]$ rm !!:1
rm class1.cpp~ class1.h~ main.cpp~ CMakeList.txt~
~]$ ls file_to_remove1 file_to_remove2
file_to_remove1 file_to_remove2
~]$ rm !!:1
rm file_to_remove1
~]$ rm !!:2
rm file_to_remove2
у меня была аналогичная потребность, в которой я хотел использовать вывод последней команды в следующую. Очень похоже на a / (pipe).
например!—4—>
$ which gradle
/usr/bin/gradle
$ ls -alrt /usr/bin/gradle
что-то вроде —
$ which gradle |: ls -altr {}
решение :
Создал этот пользовательский канал. Очень просто, используя xargs —
$ alias :='xargs -I{}'
В основном ничего, создавая короткую руку для xargs, она работает как шарм и очень удобна.
Я просто добавляю псевдоним .файл bash_profile.
это не строго решение bash, но вы можете использовать трубопровод с sed для получения последней строки предыдущих команд.
сначала давайте посмотрим, что у меня есть в папке «a»
rasjani@helruo-dhcp022206::~$ find a
a
a/foo
a/bar
a/bat
a/baz
rasjani@helruo-dhcp022206::~$
тогда ваш пример с ls и cd превратится в sed & piping во что-то вроде этого:
rasjani@helruo-dhcp022206::~$ cd `find a |sed '$!d'`
rasjani@helruo-dhcp022206::~/a/baz$ pwd
/home/rasjani/a/baz
rasjani@helruo-dhcp022206::~/a/baz$
Итак, фактическая магия происходит с sed, вы передаете то, что когда-либо выводило команду в sed, и sed печатает последнюю строку, которую вы можете использовать в качестве параметра с задними тиками. Или вы можете объединить это с xargs. («man xargs» в shell-ваш друг)
оболочка не имеет perl-подобных специальных символов, которые хранят результат Эха последней команды.
научитесь использовать символ трубы с awk.
find . | awk '{ print "FILE:" }'
в приведенном выше примере вы можете сделать:
find . -name "foo.txt" | awk '{ print "mv "" ~/bar/" | "sh" }'
find . -name foo.txt 1> tmpfile && mv `cat tmpfile` /path/to/some/dir/
еще один способ, хотя и грязные.
bash выполнения команды в переменную — linux
У меня есть команда в переменной в bash:
check_ifrunning=`ПС ОКС| grep «programmname» | grep -в «grep» | туалет -л`
Команда проверяет, работает ли в данный момент конкретная программа.
Позже в моем скрипте я хочу запросить значение переменной в точке.
Если определенная программа запущена, сценарий должен спать в течение 15 минут.
Я решил это так:
в то время как [ $check_ifrunning-eq 1 ]; do
сон 300
сделано
Теперь мой вопрос::
Будет ли скрипт выполнять команду в переменной для каждого отдельного цикла запуска или значение в переменной останется после первого выполнения?
У меня есть больше переменных в моем скрипте, которые могут изменить их значение, это был всего лишь один простой пример этого.
Спасибо за вашу помощь заранее.
С уважением.
linux
bash
shell
variables
command
Поделиться
Источник
zorro42
07 июля 2014 в 07:10
2 Ответа
1
Если вы хотите инкапсулировать свои команды, правильный способ сделать это-функция.
running () {
ps aux | grep "$1" | grep -q -v grep
}
С grep -q
вы получаете результат как код выхода, а не как выход; вы используете его просто как
if running "$programname"; then
:
В идеале, второй grep
не нужен, Но я не хотел слишком усложнять код. Он все равно не будет работать правильно, если вы ищете grep
. Правильное решение- pidof
.
См. также http://mywiki.wooledge.org/BashFAQ/050
Поделиться
tripleee
07 июля 2014 в 08:20
1
Обратите внимание, что check_ifrunning
устанавливается только один раз, в
check_ifrunning=`ps aux | grep "programmname" | grep -v "grep" | wc -l`
и что он установлен перед циклом:
while [ $check_ifrunning -eq 1 ]; do
sleep 300
done
в целях отладки можно добавить оператор echo check_ifrunning is $check_ifrunning
внутри цикла while
непосредственно перед sleep
…
Вы, вероятно, просто хотите (используя pidof(8)) — без определения или использования любой переменной check_ifrunning
bash
while [ -n "$(pidof programname)" ]; do
sleep 300
done
потому что вы хотите проверить, работает ли programname
при каждом запуске цикла!
Вы должны использовать более вложенный и более читаемый $(
… )
вместо обратных цитат.
Вы можете прочитать дополнительно Bash руководство по сценариям ….
Если вы пишете сценарий bash
, подумайте, чтобы начать его с
#!/bin/bash -vx
во время отладки. Когда вы будете удовлетворены, удалите -vx
….
Поделиться
Basile Starynkevitch
07 июля 2014 в 07:45
Похожие вопросы:
Как поместить вывод команды в переменную bash
Я хочу поместить вывод команды в переменную bash, а затем использовать эту переменную в другой команде Предположим, я хочу что-то вроде этого ls | $(variable) |awk ‘/$variable/{print here}’
Как задать переменную для вывода команды в Bash?
У меня есть довольно простой скрипт, который выглядит примерно следующим образом: #!/bin/bash VAR1=$1 MOREF=’sudo run command against $VAR1 | grep name | cut -c7-‘ echo $MOREF Когда я запускаю этот…
Периодически получая вывод команды bash в Python
Я пишу оболочку gui для команды bash в python. При выполнении команды bash первые строки 3-4 остаются неизменными, а последняя строка перезаписывается для отображения хода выполнения в текстовом…
bash как получить асинхронный вывод команды в переменную
я хочу знать, как мы можем получить вывод команды в переменную в bash вот мой код #!/bin/bash opt=svcrack -v -u100 -r1-9999 -z3 10.0.0.1 opt2=$($opt) echo myout output $opt2 выход myout output не…
Установите переменную в результат команды terminal (Bash)
Поэтому я TRYING, чтобы сделать файл bash, который вращает мой адрес MAC каждые 10 минут со случайным шестнадцатеричным номером, назначенным каждый раз. Я хотел бы иметь переменную с именем…
Как разместить вывод команды bash в переменную Python?
Как разместить вывод команды bash в переменную Python? Я пишу скрипт Python, который я хочу ввести в вывод bash команда: rpm -qa —qf ‘%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH} %{VENDOR}\n’ | grep -v…
Превратить вывод команды в переменную и обрезать переменную в bash?
У меня есть команда, которую я хочу запустить из сценария bash, который является: ec2-create-volume -s 5 -z us-west-1c Я хотел бы превратить вывод этой команды в переменную, которая является: VOLUME…
Bash получить переменную при выполнении shell
Существует ли способ получить переменную с помощью команды выполнения bash? Пример : ./exec.sh var1 var2 или с аргументами ./exec.sh -x var1 -y var2 Я искал Get variable at bash execution, но ничего…
вытяните переменную из команды (bash)
Я пытаюсь написать сценарий bash, который может извлекать переменные из его выполнения. Я действительно не могу объяснить это очень хорошо, но я хочу получить переменную из того же скрипта bash….
Как поместить команды bash / awk в переменную (не вывод команд)
Я пытаюсь просто поместить команды bash в переменную и позже запустить с функцией кода выхода. command1=$(awk -v previous_date=$reply -f $SCRIPT_HOME/tes.awk <(gzip -dc $logDir/*) > $OUTFILE)…
Как задать переменную для вывода команды в Bash? — bash
2-е редактирование 2018-02-12: добавление другого способа, поиск в нижней части этого для длительных задач!
2018-01-25 редактировать: добавить пример функции (для заполнения Варс об использовании диска )
Первая просто старая и совместимой
myPi=`echo '4*a(1)' | bc -l`
echo $myPi
3.14159265358979323844
В основном совместимый, второй способ
Поскольку вложенность может стать тяжелой, для этого была реализована скобка
myPi=$(bc -l <<<'4*a(1)')
Вложенный образец:
SysStarted=$(date -d "$(ps ho lstart 1)" +%s)
echo $SysStarted
1480656334
чтение более чем одной переменной (с башизмами )
df -k /
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/dm-0 999320 529020 401488 57% /
Если я просто хочу использовать значение:
array=($(df -k /))
вы можете увидеть переменную массива :
declare -p array
declare -a array='([0]="Filesystem" [1]="1K-blocks" [2]="Used" [3]="Available" [
4]="Use%" [5]="Mounted" [6]="on" [7]="/dev/dm-0" [8]="999320" [9]="529020" [10]=
"401488" [11]="57%" [12]="/")'
Затем:
echo ${array[9]}
529020
Но я предпочитаю вот это:
{ read foo ; read filesystem size used avail prct mountpoint ; } < <(df -k /)
echo $used
529020
1st read foo
просто пропустит строку заголовка (переменная $foo
будет содержать что-то вроде Filesystem 1K-blocks Used Available Use% Mounted on
)
Пример функции для заполнения некоторых переменных:
#!/bin/bash
declare free=0 total=0 used=0
getDiskStat() {
local foo
{
read foo
read foo total used free foo
} < <(
df -k ${1:-/}
)
}
getDiskStat $1
echo $total $used $free
Nota: declare
строка не требуется, просто для удобства чтения.
О sudo cmd | grep ... | cut ...
shell=$(cat /etc/passwd | grep $USER | cut -d : -f 7)
echo $shell
/bin/bash
(Пожалуйста, избегайте бесполезных cat
! Так что это всего на 1 fork меньше:
shell=$(grep $USER </etc/passwd | cut -d : -f 7)
Все трубы ( |
) подразумевают вилки. Где должен быть запущен другой процесс, доступ к диску, вызовы библиотек и так далее.
Таким образом, используя sed
для примера, ограничим подпроцесс только одним fork :
shell=$(sed </etc/passwd "s/^$USER:.*://p;d")
echo $shell
И с басизмами :
Но для многих действий, в основном на небольших файлах, bash мог бы сделать эту работу сам:
while IFS=: read -a line ; do
[ "$line" = "$USER" ] && shell=${line[6]}
done </etc/passwd
echo $shell
/bin/bash
или
while IFS=: read loginname encpass uid gid fullname home shell;do
[ "$loginname" = "$USER" ] && break
done </etc/passwd
echo $shell $loginname ...
Идем дальше о разделении переменных …
Посмотрите на мой ответ на вопрос, Как я могу разделить строку на разделитель в Bash?
Альтернатива: сокращение вилок за счет использования фоновых длительных задач
2-е редактирование 2018-02-12:
для предотвращения множественных вилок, таких как
myPi=$(bc -l <<<'4*a(1)'
myRay=12
myCirc=$(bc -l <<<" 2 * $myPi * $myRay ")
или
myStarted=$(date -d "$(ps ho lstart 1)" +%s)
mySessStart=$(date -d "$(ps ho lstart $$)" +%s)
Эта работа прекрасна, но запуск многих вилок является тяжелым и медленным.
а такие команды, как date
и bc
, могут выполнять множество операций, строка за строкой !!
Видеть:
bc -l <<<$'3*4\n5*6'
12
30
date -f - +%s < <(ps ho lstart 1 $$)
1516030449
1517853288
Таким образом, мы могли бы использовать длительный фоновый процесс для выполнения многих заданий, не инициируя новый fork для каждого запроса.
Нам просто нужны некоторые файловые дескрипторы и fifos , чтобы сделать это правильно:
mkfifo /tmp/myFifoForBc
exec 5> >(bc -l >/tmp/myFifoForBc)
exec 6</tmp/myFifoForBc
rm /tmp/myFifoForBc
(конечно, FD 5
и 6
должны быть неиспользованными!)… Оттуда вы можете использовать этот процесс путем:
echo "3*4" >&5
read -u 6 foo
echo $foo
12
echo >&5 "pi=4*a(1)"
echo >&5 "2*pi*12"
read -u 6 foo
echo $foo
75.39822368615503772256
В функцию newConnector
Вы можете найти мою функцию newConnector
на GitHub.Com или на моем собственном сайте (Nota на github, есть два файла, на моем сайте функция и демо объединены в 1 файл, который может быть получен для использования или просто запущен для демонстрации)
Образец:
. shell_connector.sh
tty
/dev/pts/20
ps --tty pts/20 fw
PID TTY STAT TIME COMMAND
29019 pts/20 Ss 0:00 bash
30745 pts/20 R+ 0:00 \_ ps --tty pts/20 fw
newConnector /usr/bin/bc "-l" '3*4' 12
ps --tty pts/20 fw
PID TTY STAT TIME COMMAND
29019 pts/20 Ss 0:00 bash
30944 pts/20 S 0:00 \_ /usr/bin/bc -l
30952 pts/20 R+ 0:00 \_ ps --tty pts/20 fw
declare -p PI
bash: declare: PI: not found
myBc '4*a(1)' PI
declare -p PI
declare -- PI="3.14159265358979323844"
Функция myBc
позволяет использовать фоновую задачу с простым синтаксисом и для даты:
newConnector /bin/date '-f - +%s' @0 0
myDate '2000-01-01'
946681200
myDate "$(ps ho lstart 1)" boottime
myDate now now ; read utm idl </proc/uptime
myBc "$now-$boottime" uptime
printf "%s\n" ${utm%%.*} $uptime
42134906
42134906
ps --tty pts/20 fw
PID TTY STAT TIME COMMAND
29019 pts/20 Ss 0:00 bash
30944 pts/20 S 0:00 \_ /usr/bin/bc -l
32615 pts/20 S 0:00 \_ /bin/date -f - +%s
3162 pts/20 R+ 0:00 \_ ps --tty pts/20 fw
Оттуда, если вы хотите закончить один из фоновых процессов, вам просто нужно закрыть его fd :
eval "exec $DATEOUT>&-"
eval "exec $DATEIN>&-"
ps --tty pts/20 fw
PID TTY STAT TIME COMMAND
4936 pts/20 Ss 0:00 bash
5256 pts/20 S 0:00 \_ /usr/bin/bc -l
6358 pts/20 R+ 0:00 \_ ps --tty pts/20 fw
который не нужен, потому что все fd закрываются, когда основной процесс заканчивается.
Автоматически записывать выходные данные последней команды в переменную, используя Bash?
Вопрос:
Я хотел бы иметь возможность использовать результат последней выполненной команды в следующей команде. Например,
$ find . -name foo.txt
./home/user/some/directory/foo.txt
Теперь скажем, что я хочу иметь возможность открыть файл в редакторе или удалить его или сделать что-то еще с ним, например.
mv <some-variable-that-contains-the-result> /some/new/location
Как я могу это сделать? Может быть, с помощью некоторой переменной bash?
Update:
Чтобы уточнить, я не хочу назначать вещи вручную. Для меня что-то похоже на встроенные переменные bash, например.
ls /tmp
cd $_
$_
содержит последний аргумент предыдущей команды. Я хочу нечто подобное, но с выходом последней команды.
Окончательное обновление:
Ответ Сета сработал неплохо. Несколько вещей, которые нужно иметь в виду:
- не забывайте
touch /tmp/x
при попытке решения в первый раз - результат будет сохранен только при успешном завершении кода последней команды.
Лучший ответ:
Это действительно хакерское решение, но, похоже, оно работает в большинстве случаев. Во время тестирования я заметил, что иногда это не очень хорошо работает при получении ^C в командной строке, хотя я немного изменил его поведение, чтобы немного поработать.
Этот хак — это только интерактивный режим, и я уверен, что не буду рекомендовать его никому. Фоновые команды, вероятно, вызовут еще менее определенное поведение, чем обычно. Другие ответы — лучший способ программного получения результатов.
Говоря это, вот «решение»:
PROMPT_COMMAND='LAST="`cat /tmp/x`"; exec >/dev/tty; exec > >(tee /tmp/x)'
Установите эту переменную окружения bash и выдает команды по желанию. $LAST
обычно будет выводить результат, который вы ищете:
startide seth> fortune
Courtship to marriage, as a very witty prologue to a very dull play.
-- William Congreve
startide seth> echo "$LAST"
Courtship to marriage, as a very witty prologue to a very dull play.
-- William Congreve
Ответ №1
Я не знаю никакой переменной, которая делает это автоматически. Чтобы сделать что-то помимо просто скопирования результата, вы можете повторно запустить все, что вы только что сделали, например
vim $(!!)
Где !!
— расширение истории, означающее «предыдущая команда».
Если вы ожидаете, что в нем будет одно имя файла с пробелами или другими символами, которые могут помешать правильному анализу аргументов, укажите результат (vim "$(!!)"
). Если оставить его без кавычек, он будет открывать сразу несколько файлов, если они не содержат пробелов или других токенов синтаксического анализа.
Ответ №2
Bash — это своего рода уродливый язык. Да, вы можете назначить вывод переменной
MY_VAR="$(find -name foo.txt)"
echo "$MY_VAR"
Но лучше надейтесь, что твой самый трудный find
вернул только один результат и что у этого результата не было никаких «нечетных» символов в нем, таких как возврат каретки или линейных фидов, так как они будут тихо изменены при назначении к переменной Bash.
Но лучше быть осторожным, чтобы правильно указывать вашу переменную при ее использовании!
Лучше действовать непосредственно в файле, например. с find
-execdir
(обратитесь к руководству).
find -name foo.txt -execdir vim '{}' ';'
или
find -name foo.txt -execdir rename 's/\.txt$/.xml/' '{}' ';'
Ответ №3
Существует несколько способов сделать это. Один из способов — использовать v=$(command)
, который назначит вывод команды v
. Например:
v=$(date)
echo $v
И вы также можете использовать backquotes.
v=`date`
echo $v
Из Bash Руководство для начинающих,
Когда используется обратная косая форма старого стиля, обратная косая черта сохраняет свое буквальное значение, за исключением случаев, когда следуют «$», «`» или «\». Первые обратные линии, не предшествующие обратному косую черту, завершают замену команды. При использовании формы «$ (COMMAND)» все символы между круглыми скобками составляют команду; ни один из них не рассматривается специально.
EDIT: после редактирования в вопросе кажется, что это не то, что ищет OP. Насколько мне известно, для вывода последней команды нет специальной переменной типа $_
.
Ответ №4
Это довольно легко. Использовать обратные кавычки:
var=`find . -name foo.txt`
И тогда вы можете использовать это в любое время в будущем
echo $var
mv $var /somewhere
Ответ №5
Я думаю, что вы можете взломать решение, которое включает настройку оболочки на script, содержащую:
#!/bin/sh
bash | tee /var/log/bash.out.log
Затем, если вы установите $PROMPT_COMMAND
для вывода разделителя, вы можете написать вспомогательную функцию (возможно, называемую _
), которая вы получите последний кусок этого журнала, поэтому вы можете использовать его как:
% find lots*of*files
...
% echo "$(_)"
... # same output, but doesn't run the command again
Ответ №6
Disclamers:
- Этот ответ длится полгода: D
- Я тяжелый пользователь tmux.
- Вы должны запустить свою оболочку в tmux для этого, чтобы работать
При запуске интерактивной оболочки в tmux вы можете легко получить доступ к данным, отображаемым в настоящее время на терминале. Давайте рассмотрим некоторые интересные команды:
- панель захвата tmux: она копирует отображаемые данные в один из внутренних буферов tmux. Он может скопировать историю, которая в настоящее время не видна, но сейчас нас это не интересует.
- tmux list-buffers: отображает информацию о захваченных буферах. Новейший номер будет иметь номер 0.
- tmux show-buffer -b (buffer num): это печатает содержимое данного буфера на терминале
- tmux paste-buffer -b (buffer num): это вставляет содержимое данного буфера в качестве входного
Да, это дает нам много возможностей.:) Что касается меня, я создал простой псевдоним: alias L="tmux capture-pane; tmux showb -b 0 | tail -n 3 | head -n 1"
и теперь каждый раз, когда мне нужно получить доступ к последней строке, я просто использую $(L)
для его получения.
Это не зависит от выходного потока, который использует программа (будь то stdin или stderr), метода печати (ncurses и т.д.) и кода выхода программы — данные просто должны отображаться.
Ответ №7
Вы можете настроить следующий псевдоним в своем профиле bash:
alias s='it=$($(history | tail -2 | head -1 | cut -d" " -f4-))'
Затем, набрав ‘s’ после произвольной команды, вы можете сохранить результат в переменную оболочки ‘it’.
Таким образом, пример использования:
$ which python
/usr/bin/python
$ s
$ file $it
/usr/bin/python: symbolic link to `python2.6'
Ответ №8
Я просто отстранил эту функцию bash
от предложений здесь:
grab() {
grab=$("$@")
echo $grab
}
Затем вы просто выполните:
> grab date
Do 16. Feb 13:05:04 CET 2012
> echo $grab
Do 16. Feb 13:05:04 CET 2012
Обновить: анонимный пользователь предложил заменить echo
на printf '%s\n'
, что имеет то преимущество, что он не обрабатывает такие параметры, как -e
в захваченном тексте. Итак, если вы ожидаете или испытываете такие особенности, рассмотрите это предложение. Другой вариант — вместо этого использовать cat <<<$grab
.
Ответ №9
Захват вывода с помощью backticks:
output=`program arguments`
echo $output
emacs $output
Ответ №10
Говоря «Я хочу, чтобы иметь возможность использовать результат последней выполненной команды в следующей команде», Я предполагаю, что вы имеете в виду результат любой команды, а не только найти.
Если это случай — xargs — это то, что вы ищете.
find . -name foo.txt -print0 | xargs -0 -I{} mv {} /some/new/location/{}
ИЛИ, если вам интересно сначала увидеть результат:
find . -name foo.txt -print0
!! | xargs -0 -I{} mv {} /some/new/location/{}
Эта команда имеет дело с несколькими файлами и работает как шарм, даже если путь и/или имя файла содержат пробелы.
Обратите внимание на часть mv {}/some/new/location/{}. Эта команда создается и выполняется для каждой строки, напечатанной более ранней командой. Здесь строка, напечатанная более ранней командой, заменяется вместо {}.
Отрывок из man-страницы xargs:
xargs — создавать и выполнять командные строки со стандартного ввода
Подробнее см. справочную страницу:man xargs
Ответ №11
Я обычно делаю то, что предлагали другие здесь… без назначения:
$find . -iname '*.cpp' -print
./foo.cpp
./bar.cpp
$vi `!!`
2 files to edit
Если вам нравится:
$grep -R "some variable" * | grep -v tags
./foo/bar/xxx
./bar/foo/yyy
$vi `!!`
Ответ №12
Если вы хотите только перезапустить свою последнюю команду и получить результат, будет работать простая переменная bash:
LAST=`!!`
Итак, вы можете запустить свою команду на выходе с помощью:
yourCommand $LAST
Это вызовет новый процесс и повторит вашу команду, а затем даст вам результат. Похоже на то, что вам действительно понравится, — это файл истории bash для вывода команды. Это означает, что вам нужно будет записать вывод, который bash отправляет на ваш терминал. Вы могли бы написать что-то, чтобы посмотреть /dev или/proc необходимые, но это беспорядочно. Вы также можете создать «специальную трубку» между вашим термином и bash с помощью команды tee в середине, которая перенаправляет ваш выходной файл.
Но оба эти типа являются хакерскими решениями. Я думаю, что лучше всего terminator, который является более современным терминалом с протоколированием выходных данных. Просто проверьте файл журнала для результатов последней команды. Переменная bash, аналогичная приведенной выше, сделает это еще проще.
Ответ №13
Здесь один из способов сделать это после выполнения вашей команды и решил, что вы хотите сохранить результат в переменной:
$ find . -name foo.txt
./home/user/some/directory/foo.txt
$ OUTPUT=`!!`
$ echo $OUTPUT
./home/user/some/directory/foo.txt
$ mv $OUTPUT somewhere/else/
Или, если вы заранее знаете, что хотите получить результат в переменной, вы можете использовать обратные ссылки:
$ OUTPUT=`find . -name foo.txt`
$ echo $OUTPUT
./home/user/some/directory/foo.txt
Ответ №14
Как альтернатива существующим ответам: используйте while
, если ваши имена файлов могут содержать пробелы, подобные этому:
find . -name foo.txt | while IFS= read -r var; do
echo "$var"
done
Как я уже писал, разница имеет смысл только в том случае, если вам нужно ожидать пробелов в именах файлов.
NB: единственный встроенный материал — это не о выходе, а о статусе последней команды.
Ответ №15
как добавить export $last=$(!!)
в ваши .bashrc или .profile файлы?
EDIT:
Не обращайте внимания на всевозможные глупости.
ИЗМЕНИТЬ № 2:
- Загрузите bash исходный код
- Узнать CPP
- Код в новой магической переменной
- Profit?
Ответ №16
вы можете использовать!!: 1. Пример:
~]$ ls *.~
class1.cpp~ class1.h~ main.cpp~ CMakeList.txt~
~]$ rm !!:1
rm class1.cpp~ class1.h~ main.cpp~ CMakeList.txt~
~]$ ls file_to_remove1 file_to_remove2
file_to_remove1 file_to_remove2
~]$ rm !!:1
rm file_to_remove1
~]$ rm !!:2
rm file_to_remove2
Ответ №17
У меня была аналогичная потребность, в которой я хотел использовать вывод последней команды в следующую. Очень похоже на | (Труба).
например,
$ which gradle
/usr/bin/gradle
$ ls -alrt /usr/bin/gradle
к чему-то вроде —
$ which gradle |: ls -altr {}
Решение:
Создал эту настраиваемую трубку. Действительно просто, используя xargs —
$ alias :='xargs -I{}'
В принципе ничего, создавая короткую руку для xargs, она работает как шарм и очень удобна.
Я просто добавляю псевдоним в файл .bash_profile.
Ответ №18
Это не строго решение bash, но вы можете использовать piping с sed для получения последней строки предыдущих команд.
Сначала давайте посмотрим, что у меня есть в папке «a»
rasjani@helruo-dhcp022206::~$ find a
a
a/foo
a/bar
a/bat
a/baz
rasjani@helruo-dhcp022206::~$
Затем ваш пример с ls и cd превратится в sed и piping в нечто вроде этого:
rasjani@helruo-dhcp022206::~$ cd `find a |sed '$!d'`
rasjani@helruo-dhcp022206::~/a/baz$ pwd
/home/rasjani/a/baz
rasjani@helruo-dhcp022206::~/a/baz$
Итак, реальная магия случается с sed, вы делаете то, что когда-либо выводило из когда-либо команды в sed и sed, печатает последнюю строку, которую вы можете использовать в качестве параметра с обратными тиками. Или вы можете комбинировать это с xargs также. ( «человек xargs» в оболочке — ваш друг)
Ответ №19
find . -name foo.txt 1> tmpfile && mv `cat tmpfile` /path/to/some/dir/
— это еще один способ, хотя и грязный.
Ответ №20
В оболочке нет perl-подобных специальных символов, которые сохраняют результат эха последней команды.
Научитесь использовать символ трубы с awk.
find . | awk '{ print "FILE:" $0 }'
В приведенном выше примере вы можете сделать:
find . -name "foo.txt" | awk '{ print "mv "$0" ~/bar/" | "sh" }'
Присвоение переменной результата выполнения команды BASH — bash
Я пытаюсь выполнить следующую команду внутри скрипта BASH, и я перепробовал все разумные перестановки $ (), $ {} и ` , которые я могу придумать, но я просто не смог заставить его работать. Я бы хотел присвоить результат этой команды переменной:
"scale=2; $var1/$var2" | bc
Заранее благодарю вас за ваше время и помощь.
bash
shell
Поделиться
Источник
jkovba
11 марта 2014 в 16:48
1 Ответ
4
Вам нужно echo
команд в bc
, вот так:
var=$(echo "scale=2; $var1/$var2" | bc)
Или, как предлагалось в комментариях (спасибо!) и вы используете BASH, вы могли бы использовать <<<
вместо этого:
var=$(bc <<< "scale=2; $var1/$var2")
В то время как мы занимаемся этим, вы также можете использовать документ здесь:
var=$(bc << EOF
scale=2; $var1/$var2
EOF
)
Вот тест, показывающий, что все они делают одно и то же:
var1=10
var2=2
out1=$(echo "scale=2; $var1/$var2" | bc)
out2=$(bc <<< "scale=2; $var1/$var2")
out3=$(bc << EOF
scale=2; $var1/$var2
EOF
)
echo "$out1 $out2 $out3"
выход: 5.00 5.00 5.00
Поделиться
Tom Fenech
11 марта 2014 в 16:51
Похожие вопросы:
Bash скрипты знают результат выполнения команды
Я пишу сценарий bash для запуска интеграционного теста инструмента, который я пишу. В основном я запускаю приложение с набором входных данных и сравниваю результаты с ожидаемыми значениями с помощью…
Perl экранирующий аргумент для выполнения bash
Я написал некоторый код в Perl, который выполняет некоторую команду bash в рамках ее выполнения. Моя проблема заключалась в том, что атрибуты команды bash содержали пустое пространство, внутри…
чтение результата команды bash
Раньше я использовал execute_command , найденный в бывшем awesome wiki. Эта команда использует метод io.popen и lines для возврата результата выполнения команды. Так вот, док советует избегать…
Установка переменных окружения для скрипта в локальной переменной функции bash
У меня есть функция Unix bash, которая выполняет скрипт, который анализирует пользовательские переменные среды. Я хочу избежать экспорта соответствующих переменных в bash, а вместо этого установить…
Может ли присвоение результата функции переменной разрушить возможность хвостовой оптимизации?
Всякий раз, когда у меня есть функция для вызова в конце другой, я всегда вызываю ее в той же строке, что и возврат, например, return foo(x) . Может ли присвоение результата переменной испортить…
Bash скриптинг: присвоение переменной кода возврата команды
У меня есть эта простая (даже глупая 🙂 проблема: внутри скрипта bash я пытаюсь сохранить код возврата команды в переменную с помощью S? , чтобы использовать его позже в скрипте, но S? хранится…
Bash расширение переменной массива внутри команды expect
Продолжение этого вопроса : Bash: добавление дополнительных одинарных кавычек к строкам с пробелами После сохранения аргументов команды в виде массива bash touch some file.txt file=some file.txt #…
Команда не найдена при вызове функции bash
Привет я новичок в bash scripting, но не могу понять, почему я получаю команду not found error, когда я пытаюсь присвоить локальной переменной результат этого вызова функции с параметрами 20120920…
Задайте значение переменной с результатом выполнения команды в пакетном файле Windows
При работе в среде Bash , чтобы установить значение переменной в результате выполнения команды, я обычно делаю это: var=$(command -args) где var -переменная, заданная командой command -args . Затем…
Повторный перенос переменной в среду из скрипта bash
У меня есть следующий сценарий bash. export KEY=A run_command_that_uses_KEY … export KEY=B run_command_that_uses_KEY export экспортирует присвоение переменной подшаблонам, т. е. оболочкам, которые…
Вывод команды BASH в переменную — Linux Hint
Различные типы команд bash должны запускаться с терминала в зависимости от требований пользователя. Когда пользователь запускает любую команду с терминала, он показывает вывод, если ошибки не существует, в противном случае отображается сообщение об ошибке. Иногда выходные данные команды необходимо сохранить в переменной для будущего использования. Для этой цели можно использовать функцию подстановки команд оболочки в bash. В этом руководстве показано, как с помощью этой функции можно сохранять в переменной различные типы команд оболочки.
переменная = $ (команда)
переменная = $ (команда [параметр…] аргумент1 аргумент2…)
переменная = $ (/ путь / к / команде)
ИЛИ
переменная = `команда`
переменная =` команда [опция…] аргумент1 аргументы2… `
переменная =` / путь / к / команде`
*** Примечание. Не используйте пробелы до и после знака равенства при использовании приведенных выше команд.
Вывод одной команды в переменную
Команды Bash могут использоваться без каких-либо параметров и аргументов для тех команд, где эти части являются необязательными.В следующих двух примерах показано использование простой подстановки команд.
Пример № 1:
bash ` date` Команда используется для отображения текущей даты и времени. Следующий скрипт сохранит вывод команды date в переменную $ current_date с помощью подстановки команд.
$ current_date = $ (date)
$ echo «Сегодня $ current_date»
Выход:
Пример № 2:
Команда `pwd` показывает путь к текущему рабочему каталогу.Следующий сценарий сохраняет вывод команды `pwd` в переменную $ current_dir , а значение этой переменной печатается с помощью команды ` echo` .
$ current_dir = `pwd`
$ echo» Текущий каталог: $ current_dir «
Выход:
Команда с опцией и аргументом
Параметр и аргумент являются обязательными для некоторых команд bash. В следующих примерах показано, как можно сохранить вывод команды с параметром и аргументом в переменной.
Пример № 3:
Bash ` wc` Команда используется для подсчета общего количества строк, слов и символов в любом файле. Эта команда использует -c, -w и -l в качестве параметра и имя файла в качестве аргумента для генерации вывода. Создайте текстовый файл с именем fruit.txt со следующими данными, чтобы протестировать следующий сценарий.
fruit.txt
fruit.txt
Манго
Апельсин
Банан
Виноград
Гуава
Яблоко
Выполните следующие команды, чтобы подсчитать и сохранить общее количество слов в фруктах.txt в переменную $ count_words и распечатайте значение с помощью команды echo .
$ count_words = `wc -w fruit.txt`
$ echo» Всего слов в файле fruit.txt составляет $ count_words «
Выход:
Пример № 4:
`cut` — это еще одна команда bash, которая использует параметр и аргумент для генерации вывода. Создайте текстовый файл с именем weekday.txt с названиями дней недели для запуска следующего сценария.
weekday.txt
Понедельник
Вторник
Среда
Четверг
Пятница
Суббота
Воскресенье
Создайте файл bash с именем cmdsub1.sh с помощью следующего сценария. В этом скрипте цикл и используется для чтения содержимого файла weekday.txt построчно и чтения первых трех символов каждой строки с помощью команды cut . После вырезания строковое значение сохраняется в переменной $ день .Затем, если оператор используется для проверки, значение $ день является « Sun» или нет. На выходе будет напечатано « Воскресенье — выходной », если условие истинно, в противном случае будет напечатано значение $ день .
cmdsub1.sh
#! / Bin / bash
filename = ‘weekday.txt’
при чтении строки; do
day = `echo $ line | cut -c 1-3`
if [$ day == «Sun»]
then
echo «Воскресенье — выходной»
else
echo $ day
fi
done <$ filename
Запустите сценарий.
$ cat weekday.txt
$ bash cmdsub1.sh
Выход:
Использование подстановки команд в цикле
Вы можете сохранить результат подстановки команды в любую переменную цикла, которая показана в следующем примере.
Пример 5:
Создайте файл с именем cmdsub2.sh со следующим кодом. Здесь команда ` ls -d * / ` используется для получения всего списка каталогов из текущего каталога.Здесь цикл For используется для чтения каждого каталога из вывода и сохранения его в переменной $ dirname , которая печатается позже.
cmdsub2.sh
#! / Bin / bash
для имени каталога в $ (ls -d * /)
do
echo «$ dirname»
done
Запустите сценарий.
Выход:
Использование вложенных команд
Как можно использовать несколько команд с помощью вертикальной черты (|), показано в предыдущем примере.Но вы можете использовать вложенные команды при подстановке команд, где вывод первой команды зависит от вывода второй команды и работает противоположно команде pipe (|).
Синтаксис вложенной команды:
var = `команда1 \` команда \ `
Пример № 6:
Две команды, echo и who , используются в этом примере как вложенная команда. Здесь сначала будет выполнена команда « who », которая распечатает информацию о текущем вошедшем в систему пользователе.Выходные данные команды ` who ` будут выполняться командой ` echo `, а выходные данные ` echo ` сохранятся в переменной $ var . Здесь вывод команды ` echo ` зависит от вывода команды ` who `.
$ var = `echo \` who \ `
$ echo $ var
Выход:
Использование пути к команде
Если вам известен путь к команде, вы можете запустить команду, указав путь к команде при использовании подстановки команд.В следующем примере показано использование пути к команде.
Пример № 7:
Команда `whoami` показывает имя пользователя, вошедшего в систему. По умолчанию эта команда хранится в папке / usr / bin / . Запустите следующий скрипт, чтобы запустить команду whoami , используя путь и сохранить в переменной, $ output, и распечатать значение $ output .
$ output = $ (/ usr / bin / whoami)
$ echo $ output
Выход:
Использование аргумента командной строки
Вы можете использовать аргумент командной строки вместе с командой в качестве аргумента при подстановке команд.
Пример # 8:
Создайте файл bash с именем cmdsub3.sh с помощью следующего сценария. Команда ` basename ` используется здесь для извлечения имени файла из аргумента командной строки 2 nd и сохраняется в переменной $ filename . Мы знаем, что аргумент командной строки 1 st — это имя исполняемого скрипта, которое обозначается $ 0.
#! / Bin / bash
filename = `basename $ 1`
echo» Имя файла — $ filename.«
Запустите сценарий со следующим значением аргумента.
$ bash cmdsub3.sh Рабочий стол / temp / hello.txt
Здесь — базовое имя пути, Desktop / temp / hello.txt — « hello.txt ». Таким образом, значение $ filename будет hello.txt .
Выход:
Заключение:
В этом руководстве показаны различные варианты использования подстановок команд. Если вам нужно работать с несколькими командами или зависимыми командами и временно сохранить результат для выполнения некоторых других задач позже, вы можете использовать эту функцию в своем скрипте, чтобы получить результат.
Подробности в видео:
.
Как я могу получить вывод команды в переменной bash?
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира- О компании
.Оболочка
— как назначить вывод команды Bash переменной?
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира- О компании
.Сценарий
Bash — переменное содержимое как команда для запуска
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира- О компании
.