폴더에 있는 모든 파일의 첫 번째 줄과 마지막 줄을 인쇄합니다.

폴더에 있는 모든 파일의 첫 번째 줄과 마지막 줄을 인쇄합니다.

file.log.1덮어쓴 로그 파일( 등 ) 이 많이 있습니다 file.log.2. 장치에서 로컬 컴퓨터로 복사할 때 원래 타임스탬프가 손실되었습니다. 그래서 시간순으로 정리하고 싶습니다. 문제는 무엇이 최신이고 무엇이 가장 오래된 것인지 반드시 알 수 없다는 것입니다.

내가 원하는 것은 모든 로그가 하나의 디렉토리에 있는 경우 다음과 같이 인쇄하는 것입니다.

file: file.log.1
first line: [first line that isn't whitespace]
last line: [last line that isn't whitespace]

이를 위해 Python 스크립트를 작성할 수 있지만 가능하다면 Linux 내장 스크립트를 사용하는 것이 좋습니다. awk/sed를 위한 작업인가요? 아니면 이것이 실제로 스크립팅 언어에 더 적합합니까? 대답이 '예'라면 awk/sed는 무엇을 합니까?

검색을 통해 이 awk 명령을 찾았지만 파일 이름만 허용하고 마지막 줄의 내용을 인쇄합니다(그리고 끝에는 가변 개수의 빈 줄이 있을 수 있습니다).

awk 'NR == 1 { print }END{ print }' filename

답변1

그래서 나는 sed이 대답을 좋아한다.

for file in file.log.*
do
   echo "file: $file"
   echo -n "first line: "
   cat "$file" | sed -n '/^\s*$/!{p;q}'
   echo -n "last line: "
   tac "$file" | sed -n '/^\s*$/!{p;q}'
done

답변2

awk 명령:

awk -v OFS=: '
    FNR==1 {
        # the last non-blank line from the previous file
        if (line) {print filename, fnr, line}
        filename=FILENAME
        line=""
        p=0
    } 
    /^[[:blank:]]*$/ {next} 
    !p {
        # the first non-blank line
        print FILENAME, FNR, $0; p=1
    }
    {fnr=FNR; line=$0} 
    END {print filename, fnr, line}
' *

각 파일에 대해 파일 이름, 줄 번호, 줄을 ​​콜론으로 구분하여 인쇄합니다.

GNU awk v4에는 BEGINFILE 및 ENDFILE 모드가 있어 작업이 크게 단순화됩니다.

gawk -v OFS=: '
    BEGINFILE {p=0} 
    /^[[:blank:]]*$/ {next} 
    !p {print FILENAME, FNR, $0; p=1}
    {fnr=FNR; line=$0} 
    ENDFILE {print FILENAME, fnr, line}
' *

답변3

노력하다:

awk -F'\n' -vRS="" '
  {
    print "file: " FILENAME;
    gsub(/\n[[:blank:]]+|[[:blank:]]+\n/,"");
    print "first line: " $1;
    print "last line: " $NF;
  }
' file.log.*

답변4

무엇? 펄은 없나요?

for file in file.log.*; do 
    echo "FILE: $file"; 
    perl -ne 'if(/\S/){$k++; $l=$_}; 
              print "First line: $_" if $k==1; 
              END{print "Last line: $l\n"}' "$file";  
done

설명하다

  • for file in file.log.*file.log.: 현재 디렉터리에서 이름이 로 시작하는 모든 파일을 반복하고 각 파일을 $file.
  • echo "FILE: $file";: 파일 이름을 인쇄합니다.
  • perl -ne: 현재 입력 파일을 한 줄씩 읽고( -n) 각 줄을 특수 Perl 변수로 저장한 다음 $_해당 파일에서 주어진 스크립트를 실행합니다.-e
  • if(/\S/){$k++; $l=$_}: 현재 줄이 공백이 아닌 문자( \S)와 일치하는 경우 줄을 다른 이름으로 저장 $l하고 카운터를 $k1씩 증가시킵니다.
  • print "First line: $_" if $k==1;: 그렇다면 현재 행( $_)을 인쇄합니다. 그러면 비어 있지 않은 첫 번째 줄이 인쇄됩니다.$k1
  • END{print "Last line: $l\n"}: 입력 라인을 모두 읽은 후 실행합니다. 비어 있지 않은 모든 줄을 로 저장하므로 $l파일 끝에는 $l비어 있지 않은 마지막 줄이 있습니다. 그러면 마지막 줄이 인쇄됩니다.

또 다른 방법:

for file in file.log.*; do 
    printf "FILE: %s\nFirst line: %s\nLast line: %s\n\n" \
        "$file" \
        "$(grep -Em 1 '\S' "$file")" \
        "$(tac "$file" | grep -Em1 '\S' )"; 
done

설명하다

이것은 세 개의 문자열을 인쇄하기 for위해 여기서 사용한 것과 동일한 루프입니다 printf. 파일 이름과 다음 두 명령의 출력은 다음과 같습니다.

  • grep -Pm 1 '\S' "$file": -E확장된 정규식을 활성화하여 \S"공백 없음"을 사용할 수 있도록 합니다. -m1"첫 번째 일치 항목을 찾은 후 종료"를 의미합니다 .
  • tac "$file" | grep -Em1 '\S': tac응 카운트다운 cat. 파일의 내용을 인쇄하지만 마지막 줄부터 첫 번째 줄까지 인쇄합니다. 따라서 이 명령은 비어 있지 않은 마지막 줄을 인쇄합니다.

관련 정보