我尝试了运气grep
,sed
但不知怎的,我没能成功。
我有一个大约 8 GB 大小的日志文件。我需要分析 15 分钟内的可疑活动。我找到了日志文件中需要查看的部分,并尝试提取这些行并将其保存到单独的文件中。我该如何在普通 CentOS 机器上执行此操作?
我最后一次尝试是这样的,但没有成功。当谈到sed
这些类型的命令时,我感到不知所措。
sed -n '2762818,2853648w /var/log/output.txt' /var/log/logfile
答案1
sed -n '2762818,2853648p' /var/log/logfile > /var/log/output.txt
p
用于打印
答案2
正如其他人提到的,最好的方法可能是使用 shell 重定向。sed
尽管这是个人最喜欢的,但可能不会比 will 更有效地执行此操作head
- 它的设计目的是从文件中仅抓取这么多行。
该网站上还有其他答案,这些答案清楚地表明,对于大文件,每次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
所有命令都将共享相同的输入。大多数命令在读取时会耗尽整个内文件,因此在某种{ cmd1 ; cmd2; } <infile
情况下通常cmd1
会从内文件的头部读取到其尾部,并且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
在 shell 上方最初将$n
和$d
变量设置为...
$n
wc
我的测试文件报告的行数/tmp/5mil_lines
$d
- 其中 43的商
$n/43
只是一些任意选择的除数。
- 其中 43的商
然后循环将until
其递减$n
至$d
less 值$d
。在执行此操作时,它将保存其分割计数,$s
并在循环中使用该值来增加>
名为 的命名输出文件/tmp/[num].split
。结果是,\n
每次迭代都会将其 infile 中相同数量的 ewline 分隔字段读出到新的 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
答案3
您可以借助以下命令组合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