Как можно написать скрипт, который принимает входные данные из аргумента имени файла или из стандартного ввода?
например, вы могли бы использовать less
этот способ. можно выполнить less filename
и эквивалентно cat filename | less
.
Есть ли простой способ «из коробки» сделать это? или мне нужно заново изобрести колесо и написать немного логики в скрипте?
command-line
bash
stdin
Гилад Хох
источник
источник
Ответы:
Если аргумент file является первым аргументом в вашем скрипте, проверьте, что существует аргумент (
$1
) и что это файл. Еще прочитайте ввод от stdin -Таким образом, ваш скрипт может содержать что-то вроде этого:
например, тогда вы можете назвать сценарий как
или же
Изменить некоторые объяснения сценария:
[ $# -ge 1 -a -f "$1" ]
- Если хотя бы один аргумент командной строки ($# -ge 1
) И (оператор -a) первым аргументом является файлом (-f проверяет, является ли «$ 1» файлом), то результат теста равен true.&&
является логическим оператором оболочки. Если проверка верна, назначьтеinput="$1"
иcat $input
выведите файл.||
является логическим оператором оболочки ИЛИ Если тест ложен, то следующие команды||
анализируются. вход назначен на «-». Командаcat -
читает с клавиатуры.Подводя итог, если аргумент скрипта предоставлен и это файл, тогда переменной ввода назначается имя файла. Если нет допустимого аргумента, то cat читает с клавиатуры.
источник
&& input="$1" || input="-"
и почему внеtest
оператора?$@
)?read
читает со стандартного ввода. Перенаправление его из file (./script <someinput
) или pipe (dosomething | ./script
) не заставит его работать по-другому.Все, что вам нужно сделать, это перебрать все строки на входе (и это не отличается от перебора строк в файле).
(пример кода, обрабатывает только одну строку)
Отобразится первая строка вашего стандартного ввода (либо через,
<
либо|
).источник
Вы не упоминаете, какую оболочку вы планируете использовать, поэтому я буду использовать bash, хотя это довольно стандартные вещи для всех оболочек.
Аргументы файла
Аргументы могут быть доступны через переменные
$1
-$n
($0
возвращает команду, использованную для запуска программы). Скажем, у меня есть скрипт, который простоcat
выводит n файлов с разделителем между ними:В этом случае мы передаем имя файла в cat. Однако, если вы хотите преобразовать данные в файл (без явной записи и перезаписи), вы также можете сохранить содержимое файла в переменной:
Читать со стандартного ввода
Что касается чтения из стандартного ввода, большинство оболочек имеют довольно стандартную
read
встроенную функцию , хотя существуют различия в том, как указываются приглашения (по крайней мере).Страница руководства по Bash buildins содержит довольно краткое объяснение
read
, но я предпочитаю страницу Bash Hackers .Просто:
Несколько переменных
Чтобы установить несколько переменных, просто укажите несколько имен параметров
read
:read
затем поместит одно слово из stdin в каждую переменную, сбросив все оставшиеся слова в последнюю переменную.Если введено меньше слов, чем переменных, оставшиеся переменные будут пустыми (даже если они были установлены ранее):
Запрашивает
Я
-p
часто использую флаг для подсказки:Примечание: ZSH и KSH (и, возможно, другие) используют другой синтаксис для запросов:
Значения по умолчанию
Это не совсем
read
трюк, но я часто использую его вместе сread
. Например:В принципе, если переменная (reply) существует, верните себя, но если она пуста, верните следующий параметр («N»).
источник
Самый простой способ - перенаправить stdin самостоятельно:
Или, если вы предпочитаете более краткую форму:
Теперь остальная часть вашего скрипта может просто читать со стандартного ввода. Конечно, вы можете сделать то же самое с более сложным синтаксическим анализом, вместо того, чтобы жестко задавать положение имени файла как
"$1"
.источник
exec
будет пытаться выполнить аргумент в виде команды, которая не является тем, что мы хотим здесь.if [ "$1" ] ; then exec < "$1" ; fi
в тестовый скрипт, и он выдает сообщение об ошибке, потому что команда неизвестна. То же самое с краткой формой.использовать (или цепочку) что-то еще, что уже ведет себя таким образом, и использовать
"$@"
скажем, я хочу написать инструмент, который заменит пробелы в тексте на вкладки
tr
это самый очевидный способ сделать это, но он принимает только стандартный ввод, поэтому мы должны отцепитьcat
:для примера, где используемый инструмент уже ведет себя таким образом, мы могли бы переопределить это с помощью
sed
:источник
Вы также можете сделать:
Для более аккуратных фокусов подстановки параметров в Bash см это .
источник
uglifyjs < /dev/stdin
и работает чудесно!Вы также можете сделать это простым и использовать этот код
Когда вы создаете файл сценария pass_it_on.sh с этим кодом,
Вы можете запустить
и все содержимое стандартного ввода будет просто выбрасываться на экран.
В качестве альтернативы используйте этот код, чтобы сохранить копию стандартного файла в файле и затем выбросить ее на экран.
и вот еще один пример, возможно, более читаемый, объясненный здесь:
http://mockingeye.com/blog/2013/01/22/reading-everything-stdin-in-a-bash-script/
Веселиться.
RaamEE
источник
Самый простой способ и POSIX-совместимый:
что эквивалентно
${1:--}
.Затем прочитайте файл как обычно:
источник