[英]Suppressing summary information in `wc -l` output
我使用命令wc -l
計算文本文件中的行數(我也想通過管道對所有內容進行排序),如下所示:
wc -l $directory-path/*.txt | sort -rn
輸出包括“總”行,它是所有文件的行總和:
10 total
5 ./directory/1.txt
3 ./directory/2.txt
2 ./directory/3.txt
有什么辦法可以抑制這個摘要行嗎? 或者更好的是,改變摘要行的措辭方式? 例如,用“lines”代替“10”,用“file”代替“total”。
sed
解決方案!由於總在最后一行, $d
是用於刪除最后一行的sed命令。
wc -l $directory-path/*.txt | sed '$d'
wc -l $directory-path/*.txt | sed '$d;1ilines total'
不幸的是,沒有對齊。
wc -l $directory-path/*.txt |
sed -e '
s/^ *\([0-9]\+\)/ \1/;
s/^ *\([0-9 ]\{11\}\) /\1 /;
/^ *[0-9]\+ total$/d;
1i\ lines filename'
將完成這項工作
lines file
5 ./directory/1.txt
3 ./directory/2.txt
2 ./directory/3.txt
wc
版本真的可以放在第一行: 這個是為了好玩,因為我不相信有一個wc
版本將 total 放在第一行,但是......
這個版本在任何地方都刪除了總行,並在輸出頂部添加了標題行。
wc -l $directory-path/*.txt |
sed -e '
s/^ *\([0-9]\+\)/ \1/;
s/^ *\([0-9 ]\{11\}\) /\1 /;
1{
/^ *[0-9]\+ total$/ba;
bb;
:a;
s/^.*$/ lines file/
};
bc;
:b;
1i\ lines file' -e '
:c;
/^ *[0-9]\+ total$/d
'
這更復雜,因為我們不會刪除第一行,即使它是總行。
這實際上相當棘手。
我基於 GNU coreutils 版本的wc
命令。 請注意, total
通常最后打印,而不是第一個打印(請參閱我對問題的評論)。
wc -l
為每個輸入文件打印一行,由文件中的行數和文件名組成。 (如果沒有文件名參數,則省略文件名;在這種情況下,它會計算標准輸入中的行數。)
當且僅當有多個文件名參數時,它才會打印最后一行,其中包含總行數和單詞total
。 該文檔表明無法禁止該摘要行。
除了它前面有其他輸出之外,該行與名稱恰好為total
的文件的輸出沒有區別。
因此,為了可靠地過濾掉total
,您必須讀取wc -l
的所有輸出,並且僅當輸出的總長度大於 1 時才刪除最后一行。(即使您有文件也可能會失敗名稱中帶有換行符,但您可能會忽略這種可能性。)
一種更可靠的方法是分別在每個文件上調用wc -l
,避免total
:
for file in $directory-path/*.txt ; do wc -l "$file" ; done
如果你想對輸出進行排序(你在評論中提到但在你的問題中沒有提到的東西):
for file in $directory-path/*.txt ; do wc -l "$file" ; done | sort -rn
如果您碰巧知道沒有名為total
的文件,那么快速而簡單的方法是:
wc -l $directory-path/*.txt | grep -v ' total$'
如果您想在所有文件上運行wc -l
然后過濾掉total
,這里有一個 bash 腳本應該可以完成這項工作。 根據需要調整*.txt
。
#!/bin/bash
wc -l *.txt > .wc.out
lines=$(wc -l < .wc.out)
if [[ lines -eq 1 ]] ; then
cat .wc.out
else
(( lines-- ))
head -n $lines .wc.out
fi
rm .wc.out
另一種選擇是這個 Perl 單線:
wc -l *.txt | perl -e '@lines = <>; pop @lines if scalar @lines > 1; print @lines'
@lines = <>
將所有輸入內容放入一個字符串數組中。 如果有多個,即如果最后一行是total
,則pop @lines
丟棄最后一行。
程序 wc,當它們是兩個或兩個以上文件時,總是顯示總數(wc.c 的片段):
if (argc > 2)
report ("total", total_ccount, total_wcount, total_lcount);
return 0;
最簡單的方法是只使用一個文件的 wc 並找到存在 - 一個接一個 - 文件到 wc:
find $dir -name '*.txt' -exec wc -l {} \;
或由 liborm 指定。
dir="."
find $dir -name '*.txt' -exec wc -l {} \; | sort -rn | sed 's/\.txt$//'
你能用另一個廁所嗎?
POSIX wc
( man -s1p wc
) 顯示
如果指定了多個輸入文件操作數,則應寫入附加行,格式與其他行相同,但應寫入單詞 total(在 POSIX 語言環境中)而不是路徑名和每列的總數應酌情書寫。 如果有的話,這樣的附加行會寫在輸出的末尾。
您說 Total 行是第一行,手冊說明它是最后一行,而其他 wc 根本沒有顯示。 刪除第一行或最后一行是危險的,所以我會grep -v
帶有總數的行(在 POSIX 語言環境中......),或者只是 grep 作為所有其他行的一部分的斜線:
wc -l $directory-path/*.txt | grep "/"
不是最優化的方式,因為您可以使用cat
、 echo
、 coreutils
、 awk
、 sed
、 tac
等的組合,但這會讓您想要:
wc -l ./*.txt | awk 'BEGIN{print "Line\tFile"}1' | sed '$d'
wc -l ./*.txt
將提取行數。 awk 'BEGIN{print "Line\tFile"}1'
將添加標題標題。 1
對應於標准輸入的第一行。 sed '$d'
將打印除最后一行之外的所有行。
示例結果
Line File
6 ./test1.txt
1 ./test2.txt
grep -c
的簡單性由於這些問題,我很少在腳本中使用wc -l
。 我改用grep -c
。 雖然它不如wc -l
高效,但我們不需要擔心其他問題,如摘要行、空白或分叉額外進程。
例如:
/var/log# grep -c '^' *
alternatives.log:0
alternatives.log.1:3
apache2:0
apport.log:160
apport.log.1:196
apt:0
auth.log:8741
auth.log.1:21534
boot.log:94
btmp:0
btmp.1:0
<snip>
單個文件非常簡單:
line_count=$(grep -c '^' my_file.txt)
grep -c
vs wc -l
/tmp# ls -l *txt
-rw-r--r-- 1 root root 721009809 Dec 29 22:09 x.txt
-rw-r----- 1 root root 809338646 Dec 29 22:10 xyz.txt
/tmp# time grep -c '^' *txt
x.txt:7558434
xyz.txt:8484396
real 0m12.742s
user 0m1.960s
sys 0m3.480s
/tmp/# time wc -l *txt
7558434 x.txt
8484396 xyz.txt
16042830 total
real 0m9.790s
user 0m0.776s
sys 0m2.576s
您可以像這樣使用GNU Parallel非常簡潔地解決它(以及許多其他似乎需要for
循環的問題):
parallel wc -l ::: tmp/*txt
樣本輸出
3 tmp/lines.txt
5 tmp/unfiltered.txt
42 tmp/file.txt
6 tmp/used.txt
與Mark Setchell 的回答類似,您也可以將xargs
與顯式分隔符一起使用:
ls | xargs -I% wc -l %
然后xargs
明確地不會將所有輸入發送到wc
,而是一次發送一個操作數行。
最短的答案:
ls | xargs -l wc
這是為頭部量身定做的工作:
wc -l | head --lines=-1
這樣,您仍然可以在一個進程中運行。
如果將 sed 與下面的模式刪除選項一起使用,它只會刪除存在的總行(但也包括其中包含總行的任何文件)。
wc -l $目錄路徑/*.txt | 排序-rn | sed '/總計/d'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.