Быстрая команда unix для отображения определенных строк в середине файла?
пытается отладить проблему с сервером, и мой единственный файл журнала-это файл журнала 20GB (даже без временных меток! Почему люди используют System.out.println()
вход? В производстве?!)
используя grep, я нашел область файла, на которую я хотел бы взглянуть, строка 347340107.
кроме как делать что-то вроде
head -<$LINENUM + 10> filename | tail -20
... что потребует head
чтобы прочитать первые 347 миллионов строк файла журнала, есть ли быстрая и простая команда, которая линии сброса 347340100 - 347340200 (например) в консоли?
обновление я совершенно забыл, что grep может печатать контекст вокруг матча ... это хорошо работает. Спасибо!
18 ответов
Я нашел еще два решений если вы знаете номер строки, но ничего другого (без поиска):
предполагая, что вам нужны строки от 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
, в основном.
Я бы сначала разделил файл на несколько меньших, таких как этот
$ split --lines=50000 /path/to/large/file /path/to/output/file/prefix
, а затем grep на результирующих файлах.
Я предпочитаю просто зайдя в less
и
- введя 50% перейти на половину файла,
- 43210G перейти к строке 43210
-
:43210
сделать то же самое
и тому подобное.
еще лучше: нажмите v чтобы начать редактирование (в vim, конечно!), в этом месте. Теперь, обратите внимание, что vim
имеет те же клавиши!
вы можете использовать ex
команда, стандартный редактор Unix (теперь часть Vim), например
-
отображение одной строки (например, 2-й):
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
- команда выхода из редактора (add!
сделать force quit, например-scq!
).
sed нужно будет также прочитать данные, чтобы подсчитать строки. Единственный способ ярлыка был бы возможен, если бы в файле был контекст/порядок для работы. Например, если были строки журнала, добавленные с фиксированной шириной времени / даты и т. д. вы можете использовать посмотреть утилита unix для двоичного поиска по файлам для определенных дат / времен
использовать
x=`cat -n <file> | grep <match> | awk '{print }'`
здесь вы получите номер строки, где произошло совпадение.
Теперь вы можете использовать следующую команду для печати 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, вот хорошая функция, которую можно поместить в . Он эффективен на больших файлах при печати материалов из передней части файла.
function middle()
{
startidx=
len=
endidx=$(($startidx+$len))
filename=
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, так как это зрелый язык, имеет много скрытых улучшений в пользу скорости и производительности. Имея это в виду, это делает его очевидным выбором для такой операции, так как он был первоначально разработан для обработка больших файлов журнала, текста, баз данных и т. д.
легко с 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:]]"; }