Допустим, у меня есть файл, содержащий только
a
b
c
b
a
Используя tac --separator=a file
BASH [на базе Linux на базе Debian], я получаю следующее:
# empty line
# empty line
b
c
b
aacommand@prompt # two a just before the prompt
Вопрос: Насколько я понял, --separator=a
определяет, что a
обозначает разрыв внутри строки, а не newline
.Это правильно?
Я пробовал это с другими строками, гораздо большим вводом, и в итоге получил довольно беспорядок. Все остальные варианты работают вполне правильно, я полагаю: Если я использую, то tac --before
сначала получаю около пяти, а не одну пустую строку, но затем это то, что должно произойти, верно?
решение1
tac
проще понять в случае, для которого он изначально предназначен, то есть когда разделитель является терминатором записи, т. е. разделитель появляется после последней записи. Он печатает записи (включая каждый терминатор) в обратном порядке.
$ echo -n fooabara | tac -s a; echo
rabafooa
Входные данные состоят из трех записей ( foo
, b
и r
), за каждой из которых следует разделитель a
; выходные данные состоят из трех записей ( r
, b
и foo
), за каждой из которых следует разделитель a
.
Если последняя запись не заканчивается символом конца записи, она все равно печатается первой, без разделителя записей.
$ echo -n fooabar | tac -s a; echo
rbafooa
Последняя запись r
в итоге объединяется с предпоследней записью b
без какого-либо разделителя между ними, поскольку в конце последней записи разделителя не было.
Ваш ввод выглядит немного более запутанным из-за новых строк. Давайте посмотрим, как это выглядит с запятыми вместо новых строк:
$ echo -n a,b,c,b,a, | tac -s a; echo
,,b,c,b,aa
Есть три входных записи: пустая (с терминатором a
), объемная ,,b,c,b,
(снова с терминатором) и незавершенная ,
в конце. Эти записи (каждая со своим терминатором, за исключением последней записи, у которой нет терминатора) печатаются в обратном порядке.
Ваша путаница, вероятно, возникла из-за того, что вы ожидали, что «разделитель» будет разделителем, но это неверное название: на самом деле это ограничитель записи. --before
делает его инициатором.
решение2
Следующий пример может помочь использовать эту --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
В этом примере файл records
содержит многострочные записи, каждая из которых начинается со строки ( ^...$
), которая начинается с ---
, за которой следует число ( [0-9]+
) и необязательная последовательность знаков минус ( -*
). Видно, что порядок строк в каждой записи и ее строка заголовка сохранены.
Я использую tac
этот способ для отображения записей в файлах журнала в обратном порядке, как это используется в приложениях-лентах, таких как Twitter. Например, чтобы напечатать только две последние записи в обратном порядке:
tac --before --regex --separator=^---[0-9]+-*$ example \
| awk '/^---[0-9]+-*$/ {c++} c>2 {exit}{print}'