De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.

A área de transferência - você sabia?

Colaboração: Julio Cezar Neves

Data de Publicação: 17 de agosto de 2019

Sempre imaginei, e acho que muitos de vocês também, que a área de transferência fosse um buffer que recebia o dado copiado, mas a coisa é bem mais interessante. Você já deve ter notado que, se arrastar o mouse em um texto e clicar o botão do centro (ou esquerdo e direito juntos), esse texto será copiado para o local onde está o cursor (se você não conhecia isso, experimente. Agiliza muito o copia-e-cola). Se você fizer um <CTRL>+V, será listado algo que você guardou com um <CTRL>+C e não com a arrastada do mouse. Pois é isso por si só já define dois dos buffers que existem, a saber:

  • XA_PRIMARY - Este é o padrão (default); é ele que recebe os dados quando você simplesmente arrasta o mouse sobre um texto. Esse texto pode ser recuperado clicando no botão do meio ou no da esquerda e da direita simultaneamente.

Eis um exemplo que uso para dar água na boca dos meus amigos que usam rwin. No terminal eu faço:

$ uptime | xclip   # uptime devolve o tempo sem dar boot

E aqui nesse texto vou clicar na linha a seguir com o botão do meio, veja:

00:03:54 up 50 days, 13:37, 4 users, load average: 0,39, 0,28, 0,37

Já pude dar esse exemplo porque, como já havia dito, o primário é o valor padrão e, portanto, mais simples.

  • XA_CLIPBOARD - Este recebe os dados com <CTRL>+C e recupera-os com <CTRL>+V.

    É interessante notar que, quando se copia para o primário, somente este receberá a cópia, ao passo que, se a cópia for feita para o clipboard, ambos receberão essa cópia.

  • XA_SECONDARY - Tentei muito colocar dados nesse buffer, mas não consegui nem com uso dos botões do mouse, nem com os macetes/atalhos do teclado - e, para piorar, o tio Google não me apresentou nada sobre o uso desse cara. Mas, depois de suar os bigodes, descobri que consigo municiá-lo via programas (xclip e xcel), o que me permite ter uma terceira área de transferência disponível.

Opções do comando xclip

Este comando tem inúmeras opções, mas mostrarei somente as mais usadas. São elas:

Opção | Ação
-i O xclip receberá dados da entrada primária ou arquivo(s)
-o O xclip enviará dados para a saída
-selection Seleciona buffers. Opções: primary; secondary ou clipboard[1]
-f Não filtra a saída. Joga-a na tela
-t Seleciona tipo de alvo que será copiado

[1]Para definir a seleção basta usar o primeiro caractere de cada um dos buffers. Assim, basta usar p, s ou c, respectivamente. Você também pode abreviar -selection escrevendo somente -sel.

Bem, basicamente já vimos toda a teoria, vamos aos exemplos para entendê-la.

Nos exemplos a seguir, as transferências foram efetuadas entre terminal, gedit e arquivo.

O mais simples: transferindo o conteúdo de arquivo para o buffer primário:

$ xclip -i -selection p arquivo

Mas como a opção -i é padrão e primary (p) é o padrão da opção -selection, esse exemplo poderia ser escrito assim:

$ xclip arquivo

Pronto! O conteúdo de arquivo já está armazenado no buffer primário. Você verá em diversos lugares (diria até que na maioria dos lugares) isso sendo feito dessa maneira:

$ cat arquivo | xclip      # ARGHHH!

Isso é uma perda de tempo e é uma forma de escrever mal o Shell.

Agora que você já copiou o arquivo, estando no terminal você pode devolvê-lo de duas formas:

  • Clicando no botão do meio ou no da esquerda e da direita simultaneamente (em qualquer eventualidade em que você precise do botão do meio e não o tenha - e isso é frequente em notebooks - ele sempre pode ser substituído por um clique simultâneo nos dois botões).

  • Executando o comando:

    $ xclip -o

Onde o conteúdo do buffer será passado para a saída primária (opção -o).

A diferença das duas formas é que, na primeira, os dados são interpretados e na segunda não. Caso arquivo fosse um script, da primeira forma ele seria executado, da segunda seria somente listado.

Você pode redirecionar a saída do xclip para um comando, de forma a selecionar o texto que você deseja. Para mostrar isso, vou copiar um texto que escrevi no gedit e vou baixá-lo no terminal, precedendo todos os números N por um jogo da velha, resultando #N. Escreva a linha a seguir no gedit (ou no writer):

1 2 3 de Oliveira 4

Arraste o mouse por cima, dê um <CTRL>+C e no terminal faça:

$ xclip -o -sel c | sed -r 's/([0-9]+)/#\1/g'
#1 #2 #3 de Oliveira #4

No gedit, quando copiei com <CTRL>+C, o texto copiado foi para o clipboard - daí termos dito que a saída (-o) viria deste buffer (-sel c, que é a forma abreviada de -selection clipboard). Quanto ao sed, na entrada os parênteses montam grupos com todas as sequências numéricas [0-9] com um ou mais caracteres (+) e na saída as sequências casadas são substituídas por elas mesmas (\1) precedidas por um jogo da velha (#). Se no final do comando não tivéssemos colocado um g (global), somente a primeira sequência numérica seria modificada.

Só para reforçar a ideia do sed, veja como colocar todos os números entre arrobas (@).

$ sed -r 's/([0-9]+)/@\1@/g' <<< '1: um, 20: vinte, 300: trezentos'
@1@: um, @20@: vinte, @300@: trezentos

Como os dados do xclip podem vir via pipe ou via nome do arquivo a ser copiado, para não ter trabalho, desenvolvi uma função que coleta os dados da entrada primária ou de um arquivo e os coloco no clipboard. Todo programador deve ter um arquivo no qual ele tenha as funções que mais usa. Essa função é assim:

function LeEntrada
{
if ! [[ -t 0 ]]  #  Testa se file descriptor 0 (entrada
                 #+ primária) está aberto no terminal
then
    echo -n "$(< /dev/stdin)" |
        xclip -selection c && \
            echo "Copiado para clipboard"
else
    if [[ -z "$@" ]]  # Cadê o(s) parâmetro(s)
    then
        echo "Uso:
        $0 ARQ - Manda arquivo ARQ p/ clipboard
        CMD | $0 - Manda saída de CMD p/ clipboard" >&2
        return 1
    fi
    # Então parâmetro passado foi um arquivo.
    if [[ ! -f "$@" ]]
    then
        echo  Arquivo $@ não existe
        return 1
    else
        xclip -i -selection clipboard "$@"
        echo "Arquivo "$@" copiado para clipboard"
    fi
fi
}; export -f LeEntrada

Digamos que você queira mandar uma saída simultaneamente para o buffer primário e para a área de transferência (clipboard). Se você fizer:

$ echo "Olá" | xclip -i -sel c | xclip -i -sel p

Isso não funcionará porque o primeiro xclip não gerará saída alguma para o segundo. Nesse caso é necessário usar a opção -f, que mandará o conteúdo do buffer para a saída. Veja:

$ echo "Olá" | xclip -i -sel c
$ echo "Olá" | xclip -i -sel c -f
Olá

Então, para mandar para ambos os buffers, o correto seria:

$ echo "Olá" | xclip -i -sel c -f | xclip -i -sel p 

Para encerrarmos esse assunto, só mais um exemplinho bobo (como quase todos, dos poucos que existem no man):

$ xclip -t text/html index.html

Onde a opção -t especifica que o alvo será um arquivo de html.

Só para não dizer que não falei sobre o buffer secundário, veja esse exemplo, onde uso as três áreas de transferências:

$ echo Primario   | xclip -sel p
$ echo Secundário | xclip -sel s
$ echo Clipboard  | xclip -sel c
$ xclip -o -sel p
Primario
$ xclip -o -sel s
Secundário
$ xclip -o -sel c
Clipboard

Adicionar comentário

* Campos obrigatórios
5000
Powered by Commentics

Comentários

Nenhum comentário ainda. Seja o primeiro!


Veja a relação completa dos artigos de Julio Cezar Neves