извлечение из строки в строку, а затем сохранение в отдельный файл

Я попробовал удачу с grep и sed но почему-то мне не удалось это исправить.

У меня есть файл журнала размером около 8 ГБ. Мне нужно проанализировать 15-минутный период подозрительной деятельности. Я нашел часть файла журнала, который мне нужно посмотреть, и я пытаюсь извлечь эти строки и сохранить их в отдельный файл. Как я могу сделать это на обычной машине CentOS?

Моя последняя попытка была такая, но это не сработало. Я полный новичок, когда дело доходит до sed и тех типов команд.

 sed -n '2762818,2853648w /var/log/output.txt' /var/log/logfile 

 sed -n '2762818,2853648p' /var/log/logfile > /var/log/output.txt 

p для печати

Вероятно, лучший способ сделать это – перенаправление оболочки, как упомянули другие. sed хотя, в то время как личный фаворит, вероятно, не будет делать это более эффективно, чем head – которая предназначена для захвата только такого количества строк из файла.

На этом сайте есть другие ответы, которые наглядно показывают, что для больших файлов head -n[num] | tail -n[num] head -n[num] | tail -n[num] будет превосходить sed каждый раз, но, вероятно, даже быстрее, чем это означает вообще отказаться от трубы.

Я создал файл вроде:

 echo | dd cbs=5000000 conv=block | tr \ \\n >/tmp/5mil_lines 

И я пропустил его:

 { head -n "$((ignore=2762817))" >&2 head -n "$((2853648-ignore))" } </tmp/5mil_lines 2>/dev/null | sed -n '1p;$p' 

Я использовал только sed чтобы захватить только первую и последнюю строку, чтобы показать вам …

 2762818 2853648 

Это работает, потому что когда вы группируете команды с помощью { ... ; } { ... ; } и перенаправить ввод для группы, такой как ... ; } <input ... ; } <input все из них будут использовать один и тот же вход. Большинство команд будут исчерпывать весь infile при чтении его так в { cmd1 ; cmd2; } <infile { cmd1 ; cmd2; } <infile { cmd1 ; cmd2; } <infile case Обычно cmd1 читает от главы infile до его хвоста, а cmd2 имеет ни одного.

head , однако, всегда будет искать только до сих пор через свой infile, как ему поручено делать, и поэтому в …

 { head -n [num] >/dev/null head -n [num] } <infile 

… случай, когда первый ищет [num] и выгружает свой вывод в /dev/null а второй остается, чтобы начать чтение, где первый оставил его.

Ты можешь сделать…

 { head -n "$((ignore=2762817))" >/dev/null head -n "$((2853648-ignore))" >/path/to/outfile } <infile 

Эта конструкция также работает с другими типами составных команд. Например:

 set "$((n=2762817))" "$((2853648-n))" for n do head "-n$n" >&"$#"; shift done <5mil_lines 2>/dev/null | sed -n '1p;$p' 

… который печатает …

 2762818 2853648 

Но это может также работать так:

 d=$((( n=$(wc -l </tmp/5mil_lines))/43 )) && until [ "$(((n-=d)>=(!(s=143-n/d))))" -eq 0 ] && head "-n$d" >>"/tmp/${s#1}.split" do head "-n$d" > "/tmp/${s#1}.split" || ! break done </tmp/5mil_lines 

Выше оболочки сначала устанавливает переменные $n и $d для …

  • $n
    • Количество строк, о которых сообщается wc для моего тестового файла /tmp/5mil_lines
  • $d
    • Фактор $n/43 где 43 – всего лишь произвольно выбранный делитель.

Затем он перебирается until пор, until не уменьшит значение $n на $d до значения меньше $d . При этом он сохраняет счетчик расщепления в $s и использует это значение в цикле для увеличения именованного > выходного файла с именем /tmp/[num].split . Результатом является то, что он считывает равное количество полей с разделителями \n ewline в своем infile для нового outfile для каждой итерации – так же, как и 43 раз в течение цикла. Он управляет им, не читая его infile не более 2 раз – в первый раз, когда wc делает это, чтобы подсчитывать свои строки, а для остальной части операции он только считывает столько строк, сколько он записывает в outfile каждый раз.

После запуска я проверил свои результаты, как …

 tail -n1 /tmp/*split | grep . 

ВЫВОД:

 ==> /tmp/01.split <== 116279 ==> /tmp/02.split <== 232558 ==> /tmp/03.split <== 348837 ==> /tmp/04.split <== 465116 ==> /tmp/05.split <== 581395 ==> /tmp/06.split <== 697674 ==> /tmp/07.split <== 813953 ==> /tmp/08.split <== 930232 ==> /tmp/09.split <== 1046511 ==> /tmp/10.split <== 1162790 ==> /tmp/11.split <== 1279069 ==> /tmp/12.split <== 1395348 ==> /tmp/13.split <== 1511627 ==> /tmp/14.split <== 1627906 ==> /tmp/15.split <== 1744185 ==> /tmp/16.split <== 1860464 ==> /tmp/17.split <== 1976743 ==> /tmp/18.split <== 2093022 ==> /tmp/19.split <== 2209301 ==> /tmp/20.split <== 2325580 ==> /tmp/21.split <== 2441859 ==> /tmp/22.split <== 2558138 ==> /tmp/23.split <== 2674417 ==> /tmp/24.split <== 2790696 ==> /tmp/25.split <== 2906975 ==> /tmp/26.split <== 3023254 ==> /tmp/27.split <== 3139533 ==> /tmp/28.split <== 3255812 ==> /tmp/29.split <== 3372091 ==> /tmp/30.split <== 3488370 ==> /tmp/31.split <== 3604649 ==> /tmp/32.split <== 3720928 ==> /tmp/33.split <== 3837207 ==> /tmp/34.split <== 3953486 ==> /tmp/35.split <== 4069765 ==> /tmp/36.split <== 4186044 ==> /tmp/37.split <== 4302323 ==> /tmp/38.split <== 4418602 ==> /tmp/39.split <== 4534881 ==> /tmp/40.split <== 4651160 ==> /tmp/41.split <== 4767439 ==> /tmp/42.split <== 4883718 ==> /tmp/43.split <== 5000000 

Вероятно, вы могли бы выполнить это с помощью комбинаций команд head и tail как показано ниже.

 head -n{to_line_number} logfile | tail -n+{from_line_number} > newfile 

Замените from_line_number и to_line_number номерами строк, которые вы хотите.

тестирование

 cat logfile This is first line. second Third fourth fifth sixth seventh eighth ninth tenth ##I use the command as below. I extract from 4th line to 10th line. head -n10 logfile | tail -n+4 > newfile fourth fifth sixth seventh eighth ninth tenth