행이 많은 파일이 있고 각 행에는 시작과 같이 타임 스탬프가 있습니다.
[Thread-3] (21/09/12 06:17:38:672) logged message from code.....
따라서이 로그 파일에서 자주 2 가지를 확인합니다.
- 전역 조건과 시작 시간이있는 처음 몇 개의 행도 제공됩니다.
- 마지막 정보는 다른 정보와 함께 종료 상태입니다.
파일의 처음과 마지막 몇 줄만 표시 할 수있는 빠르고 편리한 단일 명령이 있습니까?
답변
하나의 명령으로 sed
또는 awk
을 사용 하여 만들 수 있습니다 . 그러나 속도가 느슨해 져서 원인이 sed
되어 awk
어쨌든 전체 파일을 실행해야합니다. 속도 관점에서 볼 때마다 tail
+ 를 조합하여 기능을 사용하는 것이 훨씬 좋습니다 head
. 입력이 파이프 인 경우 작동하지 않는 단점이 있지만 쉘이 지원하는 경우 프로세스 대체를 사용할 수 있습니다 (아래 예 참조).
first_last () {
head -n 10 -- "$1"
tail -n 10 -- "$1"
}
그냥 시작으로
first_last "/path/to/file_to_process"
프로세스 대체를 진행하려면 (bash, zsh, ksh와 같은 쉘만 해당) :
first_last <( command )
추신. grep
“전역 조건”이 존재하는지 확인 하기 위해를 추가 할 수도 있습니다 .
답변
@rush는 head + tail을 사용하면 큰 파일에 더 효율적이지만 작은 파일 (<20 줄)의 경우 일부 줄이 두 번 출력 될 수 있습니다.
{ head; tail;} < /path/to/file
똑같이 효율적이지만 위의 문제는 없습니다.
답변
이 { head; tail; }
솔루션은 파이프 (또는 소켓 또는 사용 할 수없는 다른 파일)에서 작동 head
하지 않습니다. 블록으로 읽을 때 너무 많은 데이터를 소비하고 파이프에서 다시 커서를 검색 할 수 없기 때문에 tail
의미 하는 것 이상으로 커서를 파일 안에 남겨 둘 수 없기 때문 입니다 선택합니다.
따라서 쉘과 같이 한 번에 한 문자 씩 읽는 도구를 사용할 수 있습니다 read
(여기서는 헤드 라인과 테일 라인의 수를 인수로 사용하는 함수 사용).
head_tail() {
n=0
while [ "$n" -lt "$1" ]; do
IFS= read -r line || { printf %s "$line"; break; }
printf '%s\n' "$line"
n=$(($n + 1))
done
tail -n "${2-$1}"
}
seq 100 | head_tail 5 10
seq 20 | head_tail 5
또는 tail
awk에서 예를 들어 다음과 같이 구현하십시오 .
head_tail() {
awk -v h="$1" -v t="${2-$1}" '
{l[NR%t]=$0}
NR<=h
END{
n=NR-t+1
if(n <= h) n = h+1
for (;n<=NR;n++) print l[n%t]
}'
}
로 sed
:
head_tail() {
sed -e "1,${1}b" -e :1 -e "$(($1+${2-$1})),\$!{N;b1" -e '}' -e 'N;D'
}
(일부 sed
구현에서는 패턴 공간의 크기에 대한 제한이 낮으므로 테일 라인 수의 큰 값에는 실패합니다).
답변
bash
프로세스 대체를 사용 하여 다음을 수행 할 수 있습니다.
make_some_output | tee >(tail -n 2) >(head -n 2; cat >/dev/null) >/dev/null
줄이 순서대로 보장되지는 않지만 약 8kB보다 긴 파일의 경우에는 그럴 가능성이 높습니다. 이 8kB 컷오프는 읽기 버퍼의 일반적인 크기이며 | {head; tail;}
작은 파일에서는 작동하지 않는 이유와 관련이 있습니다.
는 cat >/dev/null
킵 할 필요가 head
살아 파이프 라인을. 그렇지 않으면 tee
일찍 종료되고에서 출력을 얻는 동안 tail
입력이 아닌 중간 부분에서 출력됩니다.
마지막으로 왜 >/dev/null
대신에 tail
다른 곳으로 옮기는가 |
? 다음과 같은 경우 :
make_some_output | tee >(head -n 2; cat >/dev/null) | tail -n 2 # doesn't work
head
stdout은 tail
콘솔 이 아닌 파이프로 파이프에 공급되며 이는 우리가 원하는 것이 아닙니다.
답변
사용 ed
(하지만 전체 파일을 RAM으로 읽습니다) :
# cf. http://wiki.bash-hackers.org/howto/edit-ed
printf '%s\n' 'H' '1,10p' '$-10,$p' 'q' | ed -s file
답변
인수를 사용할 수 있도록 Stephane의 첫 번째 솔루션 (본느 또는 POSIX 셸에서 작동) :
head_tail() {
head "$@";
tail "$@";
}
이제 당신은 이것을 할 수 있습니다 :
head_tail -n 5 < /path/to/file
물론 이것은 하나의 파일 만보 고 Stephane의 솔루션과 마찬가지로 일반 (찾을 수있는) 파일에서만 작동한다고 가정합니다.
답변
GNU 의 -u
( --unbuffered
) 옵션을 sed
사용 sed -u 2q
하면 다음에 대한 버퍼되지 않은 대안으로 사용할 수 있습니다 head -n2
.
$ seq 100|(sed -u 2q;tail -n2)
1
2
99
100
(head -n2;tail -n2)
마지막 행이 head
다음에 의해 소비되는 입력 블록의 일부인 경우 실패합니다 .
$ seq 1000|(head -n2;tail -n2)
1
2
999
1000
$ seq 100|(head -n2;tail -n2)
1
2