
我.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
不同之處在於我們不會完成結帳的情況。