Como sobrescrever stdout usando echo? [fechadas]

2

Sabemos que para substituir bar.txt , podemos usar isto:

echo "foo" > bar.txt

mas como podemos substituir a saída padrão? Eu tentei este comando:

echo "foo" >

mas falhou. Eu quero isso porque quero imprimir algo assim:

Hello  

world

I'm 

HERE 

uma palavra por vez e quero excluir a palavra anterior (uma palavra por vez na saída padrão).

    
por user78050 21.08.2014 / 13:56

5 respostas

5

echo sempre é enviado para o stdout 1 . echo foo sempre faz um write(1, "foo\n") .

Quando você executa echo foo > file , o shell altera o stdout do comando echo para um novo arquivo file . echo foo , então, ainda faz um write(1, "foo\n") , mas desta vez seu stdout (seu descritor de arquivo 1) aponta para file , não para o stdout que ele herda do shell.

Se você quiser escrever para o stdout sem que o stdout seja redirecionado , apenas escreva:

echo foo

Se você quiser que o recurso apontado por stdout seja reaberto (e truncado) antes de cada echo , então é mais complicado.

No Linux (e no Linux apenas), você pode fazer:

echo foo > /dev/fd/1
echo bar > /dev/fd/1
# now the file stdout points to (if it's a regular file) contains "bar"

No Linux, /dev/fd/1 é um link simbólico para o arquivo que está aberto no stdout. Então, abri-lo novamente com > irá truncá-lo (em outros Unices, > /dev/fd/n é como dup2(n,1) para não truncar o arquivo). Isso não funcionará se o stdout for para um soquete.

Caso contrário, você pode chamar ftruncate() no stdout (fd 1) para truncá-lo:

perl -e 'truncate STDOUT,0'
echo foo
perl -e 'truncate STDOUT,0'
echo bar

Se, em vez disso, você quiser essas palavras, quando o stdout é um terminal para substituir um ao outro na tela, você pode usar caracteres de controle do terminal para afetar o posicionamento do cursor.

 printf %s FOO
 printf '\r%s' BAR

fará com que BAR sobrescreva FOO porque \r é os caracteres de controle que instrui o terminal a mover o cursor para o início da linha.

Se você fizer isso:

printf %s FOOBAR
printf '\r%s' BAZ

no entanto, você verá BAZBAR na tela. Você pode querer usar outra seqüência de controle para limpar a linha. Enquanto \r significa que o retorno do carro é universal, a sequência de controle para limpar a tela varia de um terminal para o próximo. O melhor é consultar o banco de dados terminfo com tput para descobrir:

clr_eol=$(tput el)
printf %s FOOBAR
printf '\r%s%s' "$clr_eol" BAZ

1 se estiver usando o shell Korn ou Z, outro comando de saída que suporta gravação em outros descritores de arquivo é print : print -u2 FOO , por exemplo, escreve FOO to print é stderr. Com echo e em shells semelhantes a Bourne, você pode fazer echo >&2 FOO para obter o mesmo resultado. echo ainda está gravando em seu stdout, mas seu stdout foi duplicado no stderr do shell usando o operador de redirecionamento >&2

    
por 21.08.2014 / 14:17
2

Você pode dizer,

$ clear && printf "before" && sleep 1 && clear && printf "after\n"

Para o seu mundo Hello,

$ clear && printf "Hello" && sleep 1 && clear && printf "World" && sleep 1 && clear && printf "I'm" && sleep 1 && clear && printf "Here\n"

    
por 21.08.2014 / 14:09
1

Se você estiver imprimindo em um terminal, talvez queira omitir a nova linha ( -n ) e ter um retorno de carro explícito:

echo -en 'hello, dear\r'; sleep 5; echo -en 'world\r'; echo

(Note que você vai querer espaçar suas strings para sobrescrevê-las completamente).

    
por 21.08.2014 / 14:22
0

> de fato redireciona stdout para um arquivo. O que você tenta fazer, em outras palavras, é redirecionar o stdout para o stdout em si - o que não faz muito sentido. Você já tem stdout - > apenas informa ao shell para colocar a saída em um arquivo em vez de na tela.

O que você pode fazer é redirecionar a saída para o terminal virtual ou pseudo-terminal ao qual você tem acesso (por exemplo, comando > / dev / pts / 2), assim você pode enviar a saída de um comando para outro terminal que está sendo executado.

Você também pode criar um pipe nomeado (fifo), que aparece como um arquivo. Um comando pode gravar (seu stdout) nesse arquivo, enquanto outro comando pode ler (para seu stdin) a partir dele.

    
por 21.08.2014 / 14:16
0

Se você quiser usar echo em vez da solução de Thushi com printf , dê uma olhada na opção -e do comando echo . Isso permite que você use determinadas seqüências de escape, incluindo \b para backspace. Juntamente com a opção -n que suprime as novas linhas, você pode fazer isso:

 echo -n "Hello" && sleep 10 && echo -n -e "\b\b\b\b\bworld"
    
por 21.08.2014 / 14:19