Raw read
не будет блокироваться, если труба не пуста - он вернет столько байт, сколько доступно в трубе, даже если вы запросите больше.
Вы можете воспользоваться этим и запускать hexdump -C
при каждом успешном возврате от read
.
#define _BSD_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define N (8*512) //pipe size on my system as shown in `ulimit -a`
static char buf[N];
int main(){
ssize_t nread;
FILE* p;
for(;;){
do { nread = read(0, buf, N); }while (nread < 0 && errno == EINTR);
if(nread == 0) return 0; //EOF
if(nread < 0) goto error;
p = popen("hexdump -C", "w"); if(!p) goto error;
if(fwrite(buf, sizeof(char), nread, p) != nread) goto error;
pclose(p);
}
return 0;
error:
perror(""); return 1;
}
Вы можете сохранить это, например, как shovel.c
, а затем make shovel
(или gcc shovel.c -o shovel
) и использовать его в своей трубе.
Или, если вас это не интересует, вот ruby сниппет, который должен делать то же самое:
tail -f file |
ruby -e 'PSIZE=8*512;
while(bytes = STDIN.readpartial(PSIZE));
IO.popen("hexdump -C","w") {|p| p.syswrite(bytes) }
end '
Скорее всего, вы не захотите использовать для этого tr
, так как tr
работает только с отдельными символами (или байтами ):
$ echo abc | tr cab taxi
axt
Вместо этого я бы рекомендовал взглянуть на sed
и особенно на оператор заменыs///
().
Для передачи вывода одной программы в командную строку другой используется ключевое слово подстановка команды .
(Не буду вдаваться в подробности, так как это было домашнее задание...)