Читать функцию stdin в bash script
У меня есть набор функций bash, которые выводят некоторую информацию:
- найти-MODELNAME-в-EPSON-PPDS
- найти-MODELNAME-в-Samsung файлов PPD
- найти-MODELNAME-в-л-PPDS
- и т.д.
Я писал функции, которые считывают выходные данные и фильтруют их:
function filter-epson {
find-modelname-in-epson-ppds | sed <bla-blah-blah>
}
function filter-hp {
find-modelname-in-hp-ppds | sed <the same bla-blah-blah>
}
etc ...
Но я подумал, что было бы лучше сделать что-то вроде этого:
function filter-general {
(somehow get input) | sed <bla-blah-blah>
}
а затем вызовите другие высокоуровневые функции:
function high-level-func {
# outputs filtered information
find-modelname-in-hp/epson/...-ppds | filter-general
}
Как я могу добиться этого с помощью лучших методов bash?
Ответы
Ответ 1
Если вопрос равен How do I pass stdin to a bash function?
, то ответ будет следующим:
Функции командного интерпретатора воспринимаются обычным способом, как если бы они были командами или программами.:)
input.txt:
HELLO WORLD
HELLO BOB
NO MATCH
test.sh:
#!/bin/sh
myfunction() {
grep HELLO
}
cat input.txt | myfunction
Вывод:
[email protected]:~/scratch$ ./test.sh
HELLO WORLD
HELLO BOB
Обратите внимание, что аргументы командной строки ALSO обрабатываются обычным способом, например:
test2.sh:
#!/bin/sh
myfunction() {
grep "$1"
}
cat input.txt | myfunction BOB
Вывод:
[email protected]:~/scratch/$ ./test2.sh
HELLO BOB
Ответ 2
Чтобы быть грубо явным, что я пишу из stdin, я иногда пишу
cat - | ...
Ответ 3
Вызовите sed
напрямую. Что это.
function filter-general {
sed <bla-blah-blah>
}
Ответ 4
Я поддерживаю ответ read
, который я опубликовал fooobar.com/questions/201025/...
Но другой вариант, хороший вариант (как продолжение этого поста и @glenn jackman):
input(){ local in=$(cat -); echo you said $in; }
Хотя этот использует подоболочку...
Ответ 5
очень простой способ получить стандартный ввод переменной - использовать read
. По умолчанию он читает дескриптор файла "0", то есть стандартный ввод, то есть /dev/stdin
.
Пример функции:
input(){ local in; read in; echo you said $in; }
Пример реализации:
echo "Hello World" | input
Результат:
ты сказал Привет, мир
Дополнительная информация
Конечно, вам не нужно объявлять переменную как локальную. Я просто включил это ради хорошей формы. Обычный старый read in
делает то, что тебе нужно.
Итак, вы понимаете, как работает read
, по умолчанию он считывает данные из заданного дескриптора файла (или неявного stdin) и блоков blocks, пока не встретит символ новой строки. В большинстве случаев вы обнаружите, что они неявно будут привязаны к вашему входу, даже если вы не знали об этом. Если у вас есть функция, которая, кажется, "зависает", с этим механизмом просто запомните эту деталь (есть другие способы использования read
для решения этой проблемы).
Более надежные решения
Добавив в предыдущем примере, здесь вариант, который позволяет передавать ввод через стандартный ввод ИЛИ аргумент:
input()
{
local in=$1 if [ -z "$in" ]; then read in; fi
echo you said $in
}
С помощью этой настройки вы также можете вызывать такую функцию:
input "Hello World"
Как насчет обработки параметра stdin плюс других нескольких аргументов? Многие стандартные утилиты nix, особенно те, которые обычно работают с stdin/stdout, придерживаются общепринятой практики трактовки дефиса -
в значении "по умолчанию", что в контексте означает либо stdin, либо stdout, так что вы можете следовать соглашению, как относиться к аргумент -
как "stdin":
input()
{
local a=$1; if [ "$a" == "-" ]; then read a; fi
local b=$2
echo you said $a $b
}
Назовите это как:
input "Hello" "World"
или
echo "Hello" | input - "World"
Более того, нет никаких оснований ограничивать использование только stdin опцией только для первого аргумента! Вы можете создать супер гибкую функцию, которая может использовать ее для любого из них...
input()
{
local a=$1; if [ "$a" == "-" ]; then read a; fi
local b=$2; if [ "$b" == "-" ]; then read b; fi
echo you said $a $b
}
Зачем тебе это? Потому что вы можете сформулировать и указать любой аргумент, который вам может понадобиться...
myFunc | input "arg1" -
В этом случае я передаю второй аргумент, используя результаты myFunc
, а не единственный, имеющий параметр для первого.