
나는 행운을 시험해 보았지만 grep
어쩐지 sed
제대로 된 결과를 얻을 수 없었습니다.
크기가 약 8GB인 로그 파일이 있습니다. 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
아마도 이를 수행하는 가장 좋은 방법은 다른 사람들이 언급한 것처럼 쉘 리디렉션을 사용하는 것입니다. sed
그러나 개인적으로 선호하는 방법은 아마도 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
모든 명령이 동일한 입력을 공유하기 때문에 작동합니다. 대부분의 명령은 infile을 읽는 동안 전체 infile을 소진하므로 일반적으로 infile의 머리부터 꼬리까지 읽고 아무것도 남지 않는 { cmd1 ; cmd2; } <infile
경우가 있습니다.cmd1
cmd2
head
그러나 는 지시받은 대로 항상 해당 파일을 통해 탐색합니다.
{ 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
- 여기서 43 의 몫은
$n/43
임의로 선택된 제수입니다.
- 여기서 43 의 몫은
그런 다음 less 값으로 감소한 until
것을 반복합니다 . 그렇게 하는 동안 분할 횟수를 에 저장 하고 루프에서 해당 값을 사용 하여 . 결과적으로 각 반복마다 infile에 있는 동일한 수의 ewline으로 구분된 필드를 새로운 outfile로 읽어 들여 루프가 진행되는 동안 동일하게 43번 분할합니다. 인파일을 2번 이상 읽지 않고도 이를 관리합니다. 처음에는 라인 수를 계산하는 시기이고, 나머지 작업에서는 매번 아웃파일에 쓰는 만큼의 라인만 읽습니다.$n
$d
$d
$s
>
/tmp/[num].split
\n
wc
실행한 후 결과를 확인해 보니 다음과 같습니다.
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