tac cria saída estranha [questão de compreensão]

4

Digamos que eu tenha este arquivo, contendo apenas

a
b
c
b
a

Usando tac --separator=a file em BASH [em um Linux baseado em Debian], eu recebo isto:

                  # empty line
                  # empty line
b
c
b
aacommand@prompt  # two a just before the prompt


Pergunta : Até onde eu entendi, --separator=a define que a marca a quebra dentro da string, em vez de newline . Está certo?

Eu tentei isso com outras seqüências de caracteres muito mais uma entrada e acabou com uma bagunça. Todas as outras opções funcionam corretamente, eu presumo: Se eu usar tac --before , primeiro recebo cerca de cinco linhas vazias, mas isso é sobre o que deveria acontecer, certo?

    
por erch 25.04.2013 / 00:28

2 respostas

9

tac é mais fácil de entender no caso em que foi projetado principalmente, que é quando o separador é um terminador de registro, ou seja, o separador aparece após o último registro. Imprime os registros (incluindo cada terminador) na ordem inversa.

$ echo -n fooabara | tac -s a; echo
rabafooa

A entrada consiste em três registros ( foo , b e r ), cada um seguido pelo separador a ; a saída consiste em três registros ( r , b e foo ), cada um seguido pelo separador a .

Se o último registro não terminar com um terminador de registro, ele ainda será impresso primeiro, sem nenhum separador de registro.

$ echo -n fooabar | tac -s a; echo
rbafooa

O último registro r acaba sendo concatenado com o penúltimo registro b sem separador entre eles, já que não havia separador no final do último registro.

Sua entrada parece um pouco mais confusa por causa das novas linhas. Vamos ver com vírgulas em vez de novas linhas:

$ echo -n a,b,c,b,a, | tac -s a; echo
,,b,c,b,aa

Existem três registros de entrada: um vazio (com um terminador a ), o volumoso ,,b,c,b, (novamente com um terminador) e um , não finalizado no final. Esses registros (cada um com seu terminador, exceto o último registro que não tem um terminador) são impressos na ordem inversa.

Sua confusão provavelmente vem de esperar que o "separador" seja um separador - mas isso é um equívoco: é realmente um terminador de registro. --before faz dele um iniciador.

    
por 25.04.2013 / 03:07
1

O exemplo a seguir pode ajudar a usar a opção --regex :

$ cat records 
---1---
1
2
3
---2
A
B
C
---3--
a
b
c
$ tac --before --regex --separator=^---[0-9]+-*$ records
---3--
a
b
c
---2
A
B
C
---1---
1
2
3

Neste exemplo, o arquivo records contém registros de múltiplas linhas, cada um iniciado com uma linha ( ^...$ ) que começa com --- , seguido por um número ( [0-9]+ ) e uma sequência opcional de sinais negativos (% código%). Pode-se ver a ordem das linhas em cada registro e sua linha de cabeçalho é preservada.

Eu uso -* desta forma para mostrar entradas de arquivos de log em ordem reversa, como usado em aplicativos de feed, como o Twitter. Por exemplo, para imprimir apenas os dois últimos registros em ordem inversa:

tac --before --regex --separator=^---[0-9]+-*$ example \
 | awk '/^---[0-9]+-*$/ {c++} c>2 {exit}{print}'
    
por 13.08.2013 / 18:45