Подтвердить что ты не робот

Читать функцию 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?

4b9b3361

Ответ 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, а не единственный, имеющий параметр для первого.