sed는 패턴 사이의 줄 수를 계산합니다 - 여러 파일

sed는 패턴 사이의 줄 수를 계산합니다 - 여러 파일

.txt한 디렉토리에 여러 파일이 있습니다 . 각 파일에는 다음 섹션이 있습니다.

DONE
item 1
item 2
item 3
DONE

DONE각 파일의 두 태그 사이의 줄 수를 별도로 계산 하고 싶습니다 .

나는 사용했다이 문제이것을 생성하세요:

sed -n "/DONE/,/DONE/ p" *.txt | wc -l > ~/word_count.txt

그러나 이렇게 하면 각 파일의 개수가 단일 숫자로 결합됩니다. 대신 다음과 같은 출력을 원합니다.

file1.txt 3
file2.txt 5
file3.txt 6

답변1

더 나은 awk사용계산.

awk '
  FNR == 1 {inside = 0}
  $0 == "DONE" {
    if (inside) print FILENAME, n
    n = 0
    inside = ! inside
    next
  }
  inside {n++}' ./*.txt

그러면 DONE...DONE각 파일의 각 섹션에 대한 기록이 인쇄됩니다. 즉, 해당 섹션이 없으면 아무 것도 인쇄되지 않습니다. 이를 인쇄하려면 0GNU 구현 awkBEGINFILE특수 ENDFILE명령문이 필요합니다:

awk '
  BEGINFILE {DONE_count = 0}
  $0 == "DONE" {
    if (++DONE_count % 2 == 0) print FILENAME, n
    n = 0
    next
  }
  DONE_count % 2 {n++}
  ENDFILE {if (!DONE_count) print FILENAME, 0}' ./*.txt

awk또는 파일당 하나씩 실행합니다.

for file in ./*.txt; do
  awk '
    $0 == "DONE" {
      if (++DONE_count % 2 == 0) print FILENAME, n
      n = 0
      next
    }
    DONE_count % 2 {n++}
    END {if (!DONE_count) print FILENAME, 0}' "$file"
done

답변2

perl -lne '
   eof and !$a && print "$ARGV: ", 0+$a;          # no DONEs => ans=0
   next unless /DONE/ && !$a ... /DONE/;          # skip non-DONE ranges
   /DONE/ and !$a++ && next;                      # begin DONE range
   !/DONE/ and !eof and $a++,next;                # middle of DONE range
   !/DONE/ and eof and $a=2;                      # lone DONE => ans=0
   print "$ARGV: ", ($a-2, $a=0, close ARGV)[0];  # end of DONE range
                                                  # at the end we do 4 things: 1) subtract 2 from sum, 2) print filename+sum, 3) reset sum, and 4) skip the current file and jump to the next file in queue.
' ./*.txt

sed파일별로 이 작업을 수행할 수 있습니다 .

for f in ./*.txt; do
   printf '%s: %d\n' "$f" "$(sed -e '/DONE/,/DONE/!d; //d' "$f" | wc -l)"
done

차이점은 결제가 완료되지 않는다는 것입니다.

관련 정보