Быстрая команда unix для отображения определенных строк в середине файла?

Попытка отладить проблему с сервером, а мой единственный файл журнала - это файл журнала 20 ГБ (без временных меток!) Почему люди используют System.out.println() для регистрации? В процессе производства?!)

Используя grep, я нашел область файла, которую я хотел бы посмотреть, строка 347340107.

Кроме того, что делает что-то вроде

head -<$LINENUM + 10> filename | tail -20 

... для чего потребуется head прочитать первые 347 миллионов строк файла журнала, есть ли быстрая и простая команда, которая могла бы сбрасывать строки на панели консоли 347340100 - 347340200?

update Я полностью забыл, что grep может распечатать контекст вокруг матча... это хорошо работает. Спасибо!

Ответ 1

с GNU-grep вы можете просто сказать

grep --context=10 ...

Ответ 2

Я нашел два других решения, если вы знаете номер строки, но ничего больше (без grep):

Предполагая, что вам нужны строки от 20 до 40,

sed -n '20,40p;41q' file_name

или

awk 'FNR>=20 && FNR<=40' file_name

Ответ 3

# print line number 52
sed -n '52p' # method 1
sed '52!d' # method 2
sed '52q;d' # method 3,  efficient on large files 

метод 3 эффективен для больших файлов

быстрый способ отображения определенных строк

Ответ 4

Нет, файлы не являются адресными.

Не существует способа постоянной записи начала строки n в текстовом файле. Вы должны передать файл и подсчитать символы новой строки.

Используйте простейший/самый быстрый инструмент, который вы должны выполнить. Для меня использование head имеет гораздо больше смысла, чем grep, так как последнее является более сложным. Я не говорю, что "grep медленный", на самом деле это не так, но я был бы удивлен, если бы он был быстрее, чем head для этого случая. Это будет ошибкой в ​​head, в основном.

Ответ 5

Как насчет:

tail -n +347340107 filename | head -n 100

Я не тестировал его, но думаю, что это сработает.

Ответ 6

Сначала я разделил файл на несколько меньших, например,

$ split --lines=50000 /path/to/large/file /path/to/output/file/prefix

а затем grep в результирующих файлах.

Ответ 7

Я предпочитаю просто входить в less и

  • введите 5 0 %, чтобы перейти на полпути файла,
  • 43210 G, чтобы перейти к строке 43210
  • :43210 сделать то же самое

и тому подобное.

Еще лучше: нажмите v, чтобы начать редактирование (в vim, конечно!), в этом месте. Теперь обратите внимание, что vim имеет те же привязки клавиш!

Ответ 8

Вы можете использовать команду ex, стандартный редактор Unix (теперь часть Vim), например

  • отображает одну строку (например, вторую):

    ex +2p -scq file.txt
    

    соответствующий синтаксис sed: sed -n '2p' file.txt

  • диапазон строк (например, 2-5 строк):

    ex +2,5p -scq file.txt
    
    Синтаксис

    sed: sed -n '2,5p' file.txt

  • от указанной строки до конца (например, от 5 до конца файла):

    ex +5,p -scq file.txt
    

    sed: sed -n '2,$p' file.txt

  • несколько диапазонов строк (например, 2-4 и 6-8 строк):

    ex +2,4p +6,8p -scq file.txt
    

    sed: sed -n '2,4p;6,8p' file.txt

Выше команды могут быть протестированы со следующим тестовым файлом:

seq 1 20 > file.txt

Пояснение:

  • + или -c, за которым следует команда - выполнить команду (vi/vim) после чтения файла,
  • -s - тихий режим, также использует текущий терминал в качестве выхода по умолчанию,
  • q, за которым следует -c - команда выхода из редактора (добавьте !, чтобы сделать принудительное завершение, например -scq!).

Ответ 9

Получить ack

Установка Ubuntu/Debian:

$ sudo apt-get install ack-grep

Затем запустите:

$ ack --lines=$START-$END filename

Пример:

$ ack --lines=10-20 filename

Из $ man ack:

--lines=NUM
    Only print line NUM of each file. Multiple lines can be given with multiple --lines options or as a comma separated list (--lines=3,5,7). --lines=4-7 also works. 
    The lines are always output in ascending order, no matter the order given on the command line.

Ответ 10

Если номер вашей строки 100, читать

head -100 filename | tail -1

Ответ 11

sed нужно будет также прочитать данные для подсчета строк. Единственный способ, с помощью которого был бы доступен ярлык, был бы контекст/порядок в файле для работы. Например, если были лог-листы, добавленные с фиксированной шириной времени/даты и т.д. вы можете использовать утилиту look unix для двоичного поиска через файлы для определенных дат/времени

Ответ 12

Использование

x=`cat -n <file> | grep <match> | awk '{print $1}'`

Здесь вы получите номер строки, в которой произошло совпадение.

Теперь вы можете использовать следующую команду для печати 100 строк

awk -v var="$x" 'NR>=var && NR<=var+100{print}' <file>

или вы также можете использовать "sed"

sed -n "${x},${x+100}p" <file>

Ответ 13

С sed -e '1,N d; M q' вы будете печатать строки от N + 1 до M. Это, вероятно, немного лучше, чем grep -C, поскольку оно не пытается сопоставить строки с шаблоном.

Ответ 14

На основе ответа Sklivvz, здесь хорошая функция, которую можно поместить в файл .bash_aliases. Он эффективен при работе с огромными файлами при печати материала с передней стороны файла.

function middle()
{
    startidx=$1
    len=$2
    endidx=$(($startidx+$len))
    filename=$3

    awk "FNR>=${startidx} && FNR<=${endidx} { print NR\" \"\$0 }; FNR>${endidx} { print \"END HERE\"; exit }" $filename
}

Ответ 15

Чтобы отобразить строку из <textfile> по ее <line#>, просто выполните следующее:

perl -wne 'print if $. == <line#>' <textfile>

Если вам нужен более мощный способ показать ряд строк с регулярными выражениями - я не буду говорить, почему grep - плохая идея для этого, это должно быть довольно очевидно - это простое выражение покажет вам ваши диапазон за один проход, который вы хотите, когда имеете дело с ~ 20GB текстовыми файлами:

perl -wne 'print if m/<regex1>/ .. m/<regex2>/' <filename>

(подсказка: если в вашем регулярном выражении есть /, используйте вместо этого m!<regex>!)

Это напечатает <filename>, начиная с строки, которая соответствует <regex1> вверх до (и включает) строку, которая соответствует <regex2>.

Не требуется мастера, чтобы увидеть, как несколько настроек могут сделать его еще более мощным.

Последняя вещь: perl, поскольку это зрелый язык, имеет много скрытых улучшений, способствующих быстроте и производительности. Имея это в виду, это делает его очевидным выбором для такой операции, поскольку он был первоначально разработан для обработки больших файлов журнала, текста, баз данных и т.д.

Ответ 16

Вы можете попробовать эту команду:

egrep -n "*" <filename> | egrep "<line number>"

Ответ 17

Легко с perl! Если вы хотите получить строки 1, 3 и 5 из файла, скажем /etc/passwd:

perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd

Ответ 18

Я удивлен, что только один другой ответ (Рамана Редди) предложил добавить номера строк к выводу. Следующий поиск ищет требуемый номер строки и окрашивает вывод.

file=FILE
lineno=LINENO
wb="107"; bf="30;1"; rb="101"; yb="103"
cat -n ${file} | { GREP_COLORS="se=${wb};${bf}:cx=${wb};${bf}:ms=${rb};${bf}:sl=${yb};${bf}" grep --color -C 10 "^[[:space:]]\\+${lineno}[[:space:]]"; }