LINUX.ORG.RU

Shell-script разветвление stdin


0

0

есть следующая задача:
есть поток символов, его нужно обработать, но перед этим нужно сохранить его в файл, да ещё и в другой кодировке.
если бы мне не нужно было изменять кодировку, я бы использовал tee;
если бы мне нужно было только изменить кодировку, я бы использовал iconv.
Как их совместить, чтобы дальше на обработку пошёл неперекодированный поток?

Перекодируй готовый файл

TGZ ★★★★
()

Не уверен, что всё правильно понял, но можно сделать что-то такое:

#!/bin/sh
i=`cat /dev/stdin`
echo $i | tee
echo $i | iconv -t cp1251

и потом запускать
echo блаблабла | ./script.sh

Deleted
()

> Как их совместить, чтобы дальше на обработку пошёл неперекодированный поток?

Информация к размышлению: в tee в качестве файла может быть подан named pipe(!)

mkfifo xxx
iconv -f utf8 -t cp1251 <xxx >result_recoded.txt &
tee xxx | sort

no-dashi ★★★★★
()
Ответ на: комментарий от Deleted

В смысле, echo $i | iconv -t cp1251 > file.txt

Deleted
()

$ info coreutils 'tee invocation'

mv ★★★★★
()
Ответ на: комментарий от Svoloch

> command | iconv -f from -t to | tee | iconv -f to -t from
Двойная конвертация - первое что пришло на ум, но очевидно наличие лишней работы, а именно обратное перекодирование, так что этот вариант не очень эффективен.

> Перекодируй готовый файл

Входной поток символов предполагается распределённым в значительном промежутке времени, типа пары месяцев, при этом нужно иметь удобный доступ к файлу на всём промежутке. Так что перекодирование очень желательно вести по ходу заполнения файла.

> в tee в качестве файла может быть подан named pipe

Тоже вариант, но пайп должен лежать в какой-нибудь папке. То есть будет немного захламлять ФС; я не сказал, но параллельно ведётся несколько однородных работ, так что количество пайпов будет значительно. Впрочем, годный вариант.

> Не уверен, что всё правильно понял, но можно сделать что-то такое:

> #!/bin/sh

> i=`cat /dev/stdin`

> echo $i | tee

> echo $i | iconv -t cp1251

Я тоже не уверен что правильно понял, но больше всего похоже на то что мне нужно.

Вот это должно работать?:
#!/bin/sh
i=`cat /dev/stdin`
echo $i > /dev/stdout
echo $i | iconv > file.txt

eDeath32
() автор топика
Ответ на: комментарий от dilmah

> mkfifo /tmp/my_fifo; generate_stream | ( tee /tmp/my_fifo | iconv blahblahblah > /tmp/my_stor; ) | ( exec < /tmp/my_fifo; cat; )
выглядит слишком сложно
это перл?

eDeath32
() автор топика
Ответ на: комментарий от no-dashi

> mkfifo xxx

К сожалению, в баше не предусмотрены конструкторы -- два процесса могут юзать один и тот же ххх (но это лечится $PPID), и деструкторы -- после остановки ххх не удалится (а это уже лечится с трудом)

www_linux_org_ru ★★★★★
()

tail -f source | perltee '| iconv -f foo -t bar | logfile.log' |bla-bla-bla

perltee это что-то в этом духе (да, я тороплюсь и могу наделать кучу ошибок):

#!/usr/bin/perl -W

open(OUT, $ARGV[1]); while(<>) { print; print OUT; }

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> после остановки ххх не удалится (а это уже лечится с трудом)

man bash насчет trap, или я чего-то не понял?

dexpl ★★★★★
()
Ответ на: комментарий от Deleted

> #!/bin/sh
> i=`tee`

> echo $i

> echo $i | iconv -t cp1251 > file.txt

где здесь связь со входным потоком? да и зачем нужен tee, если разделение ввода идёт через две эхи?

Как-то так скорее^
#!/bin/sh
i=`cat /dev/stdin`
echo $i | iconv > file.txt
echo $i

Кстати, а здесь не нужно прикрутить значок "&"?

eDeath32
() автор топика

Вот исправленная версия:

tail -f source | perltee '| iconv -f foo -t bar > logfile.log' | bla-bla-bla

perltee cодержит:

#!/bin/bash

/usr/bin/perl -We "open(OUT, '$1'); while(<>) { print; print OUT; }"

Это довольно хрупко (хотя и юзабельно), так что лучше написать perltee на С.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от eDeath32

> Кстати, а здесь не нужно прикрутить значок "&"?

Кстати, а за несколько месяцев в i может накопится десяток гигабайт...

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от dexpl

> man bash насчет trap, или я чего-то не понял?

Это и есть с трудом.

Почему бы не написать mkfifo xxx && generate | tee xxx | bla-bla-bla и в гипотетическом языке убивание generate удаляло бы xxx.

Кроме того, trap не спасет от kill -9, и xxx могла бы быть структурой типа таблицы fd, и при удалении всех структур процесса из памяти ххх тоже бы удалилась (это может даже претензия к ядру?)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> trap не спасет от kill -9

AFAIU, от kill -9 ничто не спасет

dexpl ★★★★★
()
Ответ на: комментарий от eDeath32

>пайп должен лежать в какой-нибудь папке

Его можно убивать после открытия (mkfifo имя; команды & rm имя ; wait).

Башистам можно посмотреть в мане "Process Substitution" -- это, скорее всего, то же, только реализовано "ниже". Примерно так (самому не встречалось, могу ошибаться):

src | tee >(iconv >archive) | dst

DonkeyHot ★★★★★
()
Ответ на: комментарий от DonkeyHot

> Его можно убивать после открытия (mkfifo имя; команды & rm имя ; wait).

по идее можно сделать exec < fifo и exec > fifo в двух подшеллах (в скобках) и после этого удалить.

dilmah ★★★★★
()
Ответ на: комментарий от DonkeyHot

Благодарю всех за помощь. Дальше я как-нибудь сам)

eDeath32
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.