
Я искал это в Google и искал в Stack, но не нашел того, что мне нужно. Я пока не могу с этим разобраться.
Итак, предположим, у меня есть скрипт sh, который является всего лишь оберткой gzip (просто в качестве примера). В командной строке я хочу передать вывод чего-то (например, mysqldump
) в мой скрипт. Затем этот скрипт должен взять ввод и передать его в gzip.
Пример командной строки:
mysqldump somedb | myscript > somefile.dmp.gz
Пример myscript (то, что я попробовал):
#!/usr/bin/env sh
read inp
command="echo \"$inp\" | gzip"
eval $command
Вероятно, в этом примере много чего не так. Помогите, пожалуйста? :)
Решение (для тех, кто его ищет)
Благодаря объяснениям ниже я теперь понимаю, что выполнение команды в SH-скрипте просто передаст входные данные, переданные в скрипт, точно так же, как и при непосредственном выполнении команды.
Итак, в этом случае:
файл cat | gzip
будет делать то же самое, что:
мойскрипт:
#!/usr/bin/env sh
gzip
файл cat | ./myscript
Поэтому я хотел бы отметить, что в моем случае была еще одна проблема: в моем реальном скрипте я попытался проверить, есть ли входной поток, прочитав его следующим образом:
read inp
if [ -z "$inp" ]; then
echo "No input"
exit;
fi
Оказывается read inp
, после этого входная труба пуста.
решение1
#!/bin/sh
gzip -c
Этого было бы достаточно.
$ mysqldump ... | ./script >out.gz
gzip -c
будет считывать несжатые данные со своего стандартного ввода и записывать сжатые данные на свой стандартный вывод.
Стандартный ввод обеспечивается каналом, а стандартный вывод перенаправляется в файл. Каналирование и перенаправление выполняются вызывающей оболочкой.
Немного более сложный пример, который берет sed
выражение в командной строке и преобразует входные данные в соответствии с ним или просто пересылает данные, если выражение не использовалось:
#!/bin/sh
if [ -n "$1" ]; then
sed -e "$1"
else
cat
fi
(здесь использование sed -e ""
имело бы тот же эффект, что и cat
, но мне нужен был более сложный пример)
$ utility | ./script "1,5d" >out
... удалит первые пять строк вывода из utility
.
решение2
Я не уверен, какая часть вашего сценария является простым недопониманием, а какая — сложностью, потому что вы пытаетесь проиллюстрировать сложную ситуацию на более простом примере.
Сказав это, можно сказать, что это соответствует вашему вопросу:
#!/bin/sh
gzip "$@"
решение3
Чтобы использовать read
, прочитать часть входных данных и проверить, пусты они или нет, вам придется использовать оболочку, zsh
которая может хранить любое байтовое значение в своих переменных, например:
#! /bin/zsh -
if LC_ALL=C read -ru0 -k1 byte; then
# one byte was read, the input is not empty
(printf %s "$byte"; cat) | gzip
else
echo >&2 No input
fi
Или используйте какую-либо форму кодирования:
#! /bin/sh -
# get the value of the first byte as octal:
byte=$(od -An -N1 -vto1 | tr -cd 0-7)
if [ -n "$byte" ]; then
(printf "\\$byte"; cat) | gzip
else
echo >&2 No input
fi