A opção do comando tac cria uma saída estranha

A opção do comando tac cria uma saída estranha

Digamos que eu tenha este arquivo, contendo nada além de

a
b
c
b
a

Usando tac --separator=a fileno BASH [em um Linux baseado em Debian], recebo o seguinte:

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


Pergunta: Pelo que entendi, --separator=adefine que amarca a quebra dentro da string, ao invés de newline.Isto está certo?

Eu tentei isso com outras strings e muito mais entradas e acabei com uma bagunça. Todas as outras opções funcionam bem, presumo: se eu usar, tac --beforeprimeiro recebo cerca de cinco linhas vazias, mas isso é o que deveria acontecer, certo?

Responder1

tacé mais fácil de entender no caso para o qual 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, be r), cada um seguido pelo separador a; a saída consiste em três registros ( r, be 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 separador de registros.

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

O último registro racaba concatenado com o penúltimo registro bsem nenhum separador entre eles, pois não havia separador no final do último registro.

Sua entrada parece um pouco mais confusa por causa das novas linhas. Vamos ver isso 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), um 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 possui terminador) são impressos na ordem inversa.

Sua confusão provavelmente vem de esperar que o “separador” seja um separador – mas isso é um nome impróprio: é realmente um terminador de registro. --beforeem vez disso, torna-o um iniciador.

Responder2

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

$ 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 recordscontém registros multilinhas, cada um iniciado com uma linha ( ^...$) que começa com ---, seguida por um número ( [0-9]+) e uma sequência opcional de sinais de menos ( -*). Pode-se ver a ordem das linhas em cada registro e sua linha de cabeçalho são preservadas.

Eu uso tacessa forma para mostrar as entradas dos arquivos de log na ordem inversa, conforme 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}'

informação relacionada