Ответ 1
с GNU-grep вы можете просто сказать
grep --context=10 ...
Попытка отладить проблему с сервером, а мой единственный файл журнала - это файл журнала 20 ГБ (без временных меток!) Почему люди используют System.out.println()
для регистрации? В процессе производства?!)
Используя grep, я нашел область файла, которую я хотел бы посмотреть, строка 347340107.
Кроме того, что делает что-то вроде
head -<$LINENUM + 10> filename | tail -20
... для чего потребуется head
прочитать первые 347 миллионов строк файла журнала, есть ли быстрая и простая команда, которая могла бы сбрасывать строки на панели консоли 347340100 - 347340200?
update Я полностью забыл, что grep может распечатать контекст вокруг матча... это хорошо работает. Спасибо!
с GNU-grep вы можете просто сказать
grep --context=10 ...
Я нашел два других решения, если вы знаете номер строки, но ничего больше (без grep):
Предполагая, что вам нужны строки от 20 до 40,
sed -n '20,40p;41q' file_name
или
awk 'FNR>=20 && FNR<=40' file_name
# print line number 52
sed -n '52p' # method 1
sed '52!d' # method 2
sed '52q;d' # method 3, efficient on large files
метод 3 эффективен для больших файлов
быстрый способ отображения определенных строк
Нет, файлы не являются адресными.
Не существует способа постоянной записи начала строки n в текстовом файле. Вы должны передать файл и подсчитать символы новой строки.
Используйте простейший/самый быстрый инструмент, который вы должны выполнить. Для меня использование head
имеет гораздо больше смысла, чем grep
, так как последнее является более сложным. Я не говорю, что "grep
медленный", на самом деле это не так, но я был бы удивлен, если бы он был быстрее, чем head
для этого случая. Это будет ошибкой в head
, в основном.
Как насчет:
tail -n +347340107 filename | head -n 100
Я не тестировал его, но думаю, что это сработает.
Сначала я разделил файл на несколько меньших, например,
$ split --lines=50000 /path/to/large/file /path/to/output/file/prefix
а затем grep в результирующих файлах.
Я предпочитаю просто входить в less
и
:43210
сделать то же самоеи тому подобное.
Еще лучше: нажмите v, чтобы начать редактирование (в vim, конечно!), в этом месте. Теперь обратите внимание, что vim
имеет те же привязки клавиш!
Вы можете использовать команду 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!
).Получить 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.
Если номер вашей строки 100, читать
head -100 filename | tail -1
sed нужно будет также прочитать данные для подсчета строк. Единственный способ, с помощью которого был бы доступен ярлык, был бы контекст/порядок в файле для работы. Например, если были лог-листы, добавленные с фиксированной шириной времени/даты и т.д. вы можете использовать утилиту look unix для двоичного поиска через файлы для определенных дат/времени
Использование
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>
С sed -e '1,N d; M q'
вы будете печатать строки от N + 1 до M. Это, вероятно, немного лучше, чем grep -C
, поскольку оно не пытается сопоставить строки с шаблоном.
На основе ответа 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
}
Чтобы отобразить строку из <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, поскольку это зрелый язык, имеет много скрытых улучшений, способствующих быстроте и производительности. Имея это в виду, это делает его очевидным выбором для такой операции, поскольку он был первоначально разработан для обработки больших файлов журнала, текста, баз данных и т.д.
Вы можете попробовать эту команду:
egrep -n "*" <filename> | egrep "<line number>"
Легко с perl! Если вы хотите получить строки 1, 3 и 5 из файла, скажем /etc/passwd:
perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd
Я удивлен, что только один другой ответ (Рамана Редди) предложил добавить номера строк к выводу. Следующий поиск ищет требуемый номер строки и окрашивает вывод.
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:]]"; }