Как вставить встроенный (возможно, heredoc?) скрипт Python в потоковый конвейер bash stdin/stdout

Недавно я проделал значительную работу на python и хотел бы иметь возможность использовать его функции вместо встроенных команд оболочки/bash/скриптов оболочки.

Итак, для конвейера оболочки, подобного этому:

echo -e "Line One\nLine Two\nLine Three" | (cat<<-HERE | python
import sys
print 'stdout hi'
for line in sys.stdin.readlines():
  print ('stdout hi on line: %s\n' %line)
HERE
) | tee -a tee.out

Все, что напечатано, это "stdout hi"

Что здесь нужно исправить?

Благодарность!


person WestCoastProjects    schedule 13.06.2013    source источник


Ответы (1)


Было бы лучше, если бы вы объяснили, какова ваша цель с этой конструкцией. Может, можно упростить?

Проблема с этим сценарием в том, что echo переходит в stdin инкапсулирующей оболочки, инициированной нотацией (...). Но внутри оболочки стандартный ввод переопределяется как heredoc. в python, чтобы он читал скрипт со стандартного ввода, который теперь поступает из канала heredoc.

Итак, вы попробуйте что-то вроде этого:

echo -e "Line One\nLine Two\nLine Three" |  python <(cat <<HERE
import sys
print "stdout hi"
for line in sys.stdin:
  print line.rstrip()
print "stdout hi"
HERE
)

Выход:

stdout hi
Line One
Line Two
Line Three
stdout hi

Теперь скрипт читается из /dev/fd/<filehandle>, поэтому stdin может использоваться каналом echo.

РЕШЕНИЕ № 2

Есть другое решение. Скрипт можно отправить на стандартный ввод python как вот документ, но тогда входной канал должен быть перенаправлен на другой файловый дескриптор. Для этого в сценарии должна использоваться функция типа fdopen(3). Я не знаком с python, поэтому показываю Пример perl:

exec 10< <(echo -e "Line One\nLine Two\nLine Three")

perl <<'XXX'
print "stdout hi\n";
open($hin, "<&=", 10) or die;
while (<$hin>) { print $_; }
print "stdout hi\n";
XXX

Здесь echo перенаправляется на дескриптор файла 10, который открывается внутри скрипта.

Но часть echo можно удалить (-1 fork), используя другой вотдокумент:

exec 10<<XXX
Line One
Line Two
Line Three
XXX

МНОГОСТРОЧНЫЙ SCIPRT

Или просто введите несколько скриптов, используя опцию -c:

echo -e "Line One\nLine Two\nLine Three"|python -c 'import sys
print "Stdout hi"
for line in sys.stdin:
  print line.rstrip()
print "Stdout hi"'
person TrueY    schedule 13.06.2013
comment
Может быть, конструкция, которую вы показываете, python ‹ (подоболочка) - это то, чего мне не хватало, я сейчас пробую - person WestCoastProjects; 14.06.2013
comment
@javadba: Но почему бы не использовать python -c '...' вместо версии <(...)? Он более чистый. Или, если вам нужно создать скрипт в файле, вы можете создать временный файл (mktemp(1)) и перенаправить туда скрипт. - person TrueY; 14.06.2013
comment
У меня многострочный скрипт. Как это можно сделать с помощью python -c без того, чтобы оболочка возилась с кавычками? - person WestCoastProjects; 14.06.2013
comment
@javadba: я добавил еще два решения. Последний просто использует -c. - person TrueY; 14.06.2013