簡體   English   中英

抑制`wc -l`輸出中的摘要信息

[英]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解決方案!

1.短而快

由於總在最后一行, $d是用於刪除最后一行的命令。

wc -l $directory-path/*.txt | sed '$d'

2.添加標題行:

wc -l $directory-path/*.txt | sed '$d;1ilines total'

不幸的是,沒有對齊。

3. 對齊:將左列格式化為 11 個字符寬度。

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

4. 但如果你的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 "/"

不是最優化的方式,因為您可以使用catechocoreutilsawksedtac等的組合,但這會讓您想要:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM