逐行提取,然後保存到單獨的文件中

逐行提取,然後保存到單獨的文件中

我嘗試了運氣grepsed但不知怎的,我沒能成功。

我有一個大約 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只是一些任意選擇的除數。

然後它循環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

相關內容