파일의 첫 번째 줄과 마지막 줄을 표시하는 명령

파일의 첫 번째 줄과 마지막 줄을 표시하는 명령

여러 줄이 있는 파일이 있는데 각 줄의 시작 부분에 타임스탬프가 있습니다.

[Thread-3] (21/09/12 06:17:38:672) logged message from code.....

그래서 제가 항상 이 로그 파일에서 확인하는 것이 두 가지 있습니다.

  1. 처음 몇 줄에는 전역 조건이 있으며 시작 시간도 제공됩니다.
  2. 마지막 몇 줄에는 종료 상태와 기타 정보가 포함되어 있습니다.

파일의 첫 번째 줄과 마지막 줄만 표시할 수 있는 빠르고 편리한 단일 명령이 있습니까?

답변1

@rush는 큰 파일의 경우 head + tail을 사용하는 것이 옳지만 작은 파일(20줄 미만)의 경우 일부 줄이 두 번 출력될 수 있습니다.

{ head; tail;} < /path/to/file

마찬가지로 잘 작동하지만 위의 문제는 없습니다.

답변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 )

grepPS "전역 조건"이 존재하는지 확인하기 위해 하나를 추가할 수도 있습니다 .

답변3

이 솔루션은 청크 단위로 읽을 때 너무 많은 데이터를 소비할 수 있고 파이프에서 검색할 수 없으면 커서가 범위를 벗어날 수 있으므로 { head; tail; }파이프(또는 소켓 또는 기타 검색할 수 없는 파일)에서는 작동하지 않습니다. headfile 그 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

또는 awk로 구현하세요 tail. 예를 들면 다음과 같습니다.

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구현에서는 패턴 공간의 크기에 대한 제한이 낮으므로 후행 줄의 값이 더 크면 실패합니다.)

답변4

프로세스 대체를 사용하면 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

headtail표준 출력은 콘솔 대신 파이프로 이동하는데 , 이는 우리가 전혀 원하는 것이 아닙니다.

관련 정보