Команда Unix для списка части конца файла журнала от строки, содержащей только дефисы к концу файла

У меня есть долгий файл журнала, где каждая запись начинается со строки containg только дефисы.

0
задан 13.07.2010, 15:02

8 ответов

Можно сделать это со сценарием оболочки таким образом:

#!/bin/bash
if [[ -z "$1" ]] ; then
    echo Usage: $0 '<inputFile>'
    exit 1
fi
line=$(grep -n '^--*$' "$1" | tail -1 | sed 's/:.*//')
if [[ -z "${line}" ]] ; then
    cat "$1"
else
    sed "1,${line}d" "$1"
fi

Учитывая входной файл:

this is line 1
-------
this is line 3
-------
this is line 5
this is line 6

это производит:

this is line 5
this is line 6

Посредством объяснения, grep -n производит серию строк как:

2:-------
4:-------

где 2 и 4 номера строки. tail -1 затем просто отфильтровывает все кроме последнего и sed полосы все от двоеточия в конец строки, оставляя просто номер строки

Затем если не было никаких строк с желаемым шаблоном, он просто производит весь файл. Иначе это удаляет все строки между 1 и последнюю строку дефиса.


Как в стороне, мой исходный ответ включал это awk отрывок, который обработает файл только однажды:

awk '/^--*$/{s=""}{s=s$0"\n";}END{print s}'

Однако имейте в виду, что это работает путем накопления строк в строку и убирания строки каждый раз, когда это находит строку дефиса. Затем в конце это просто производит строку (все строки после последней строки дефиса).

В то время как на первый взгляд, это, может казаться, более эффективно, это, кажется, не в действительности. В (по общему признанию неисчерпывающих) тестах в моей системе это на самом деле работало вполне немного медленнее, я думаю, чтобы сделать со строкой многих, добавляет продолжение. Факт - то, что решение для сценария, кажется, быстрее несмотря на то, что оно делает несколько передач данных (возможно, потому что каждая передача очень ограничена в том, что оно делает).

3
ответ дан 24.11.2019, 02:39
awk -vRS="-+" 'END{print}' ORS="" file
3
ответ дан 24.11.2019, 02:39

Можно также сделать это с sed:

% cat t.txt
this is line 1
this is line 2
-------
this is line 3
----
this is line 4
-------
this is line 5
this is line 6
% sed -n -e '/^---*/{h;d;}' -e H -e '${g;p;}' t.txt
-------
this is line 5
this is line 6
% 

(с некоторыми семенами те точки с запятой должны были бы быть новыми строками).

2
ответ дан 24.11.2019, 02:39

Я думаю, что это может быть легко сделано с помощью sed. Вы хотите, чтобы команда нашла финал (т.е. в последний раз) строкой единственных дефисов, и Вы хотите print от той точки в конец файла.

К сожалению, я не очень хорош с sed. Надеясь кто-то еще может уточнить.


Править

ХОРОШО, sed не идеально. Вот то, как сделать это с ex, близнец только для текста vi:

ex filename
$
?----------
.,$p
q
1
ответ дан 24.11.2019, 02:39
tac file | grep -B 10000 -m 1 -- '------' | tac
1
ответ дан 24.11.2019, 02:39

Это - вероятно, не наиболее эффективное решение:

#!/bin/bash

file=$1
pattern='^-+$'
declare -i count=0
declare -i index=0

while read -r line
do
    count+=1
    [[ $line =~ $pattern ]] && index=$count
done < "$file"

tail -n "$((count - index))" "$file"
0
ответ дан 24.11.2019, 02:39

Использовать tac и sed:

$ cat log-file 
---
first
------
second
---
last

$ tac log-file | sed -e '/^-\+$/,$d' | tac
last
0
ответ дан 24.11.2019, 02:39
echo "`sed -n '/^--*$/=' <file> | tail -1`,\$p" <file>  | xargs sed -n

Но мне нравится решение Norman Gray намного лучше. Май как он еще больше, если он объяснил это :-)

0
ответ дан 24.11.2019, 02:39

Теги

Похожие вопросы