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每個文件中的每個部分列印一條記錄,這表示如果沒有這樣的部分,則不會列印任何內容。要列印0這些內容,您需要 GNU 實作awk及其BEGINFILE特殊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

不同之處在於我們不會完成結帳的情況。

相關內容