2011-05-05 54 views
3

我用grep只返回模式(-o)之間的字符串,數字文件內,例如文件匹配模式後停止grep,不是整行?與長線/單線

grep -i -r -o 'Rows="[^#][^"]*"' * 

我想它的第一個匹配後停止模式,我試過grep -m NUM/--max-count = NUM​​ 但是這樣在NUM匹配後停止讀取文件,而不是模式,不幸的是,這個文件夾中的所有文件都是一個長行。

可以在第一個匹配模式後停止grep,或者我應該用其他方法做這件事?

*獎金問題 - 能夠輸出爲「匹配模式」'文件名',所以我可以排序嗎?

回答

-1

我沒有測試它,但我想嘗試:

find -type f -print0 | xargs -0 -r cat | grep -m 1 -i -o 'Rows="[^#][^"]*"' 
+0

我不認爲這比問題中的建議更好。 'find | cat'組合符合grep的功能。 – JXG 2011-08-25 08:41:36

+0

@JXG:但至少它在第一場比賽後關閉了管道。因此,根據計劃的不同,可能不會打開所有文件,並且該命令會比原始提案更早退出。 – 2012-03-14 22:21:24

0

據我所知,有沒有辦法在grep做到這一點。實際上,大多數Unix工具都是固定的基於行的。例如,我認爲在sed中沒有辦法只打印出一部分內容。即使在awk,也可能有一種方法來拼湊一些東西在一起,但我的猜測是,它會令人不滿意。

如果您的系統上有GNU awk的,不過,試試這個:

gawk 'BEGIN {RS="pattern"} {print RT, FILENAME; exit}' filename 

RS設置記錄分隔符(通常是新行)是模式。 RT是由RS匹配的文本。 FILENAME是不言自明的。 exit停止執行。所以,在第一條記錄之後,awk將打印模式文本和文件名,並退出。這不適用於多個文件,因爲這裏的退出是無條件的。

如果您需要在目錄結構中的所有文件運行它,使用findxargs,也不要退出,除非你找到的東西:

find . -type f -print0 | xargs -0 gawk 'BEGIN {RS="pattern"} {print RT, FILENAME; if (RT != "") exit}' 

這打印出的文件名(前由一個空格)沒有模式的所有東西,但打印出模式和文件名,當它遇到第一個模式,然後停止。

當然,您需要小心一點,因爲記錄分隔符可能根本就不存在,因此gawk可能會將文件的全部內容淹沒到其緩衝區中,並且可能會導致內存不足。 (當我在我的系統上測試時,我在490 MB時失敗了。)

0

想到兩個想法;

perl -nle '/(Rows="[^#][^"]*")/ or continue; print $ARGV, ":", $1; exit 0' files ... 

然而,這將在處理它之前讀取整行。另一個想法是預處理文件傳遞到grep,像這樣的黑客,也許前:

for file in *; do 
    # Replace every R with newline, 
    # and every newline with dot. 
    # Your tr's syntax for newline may be different 
    tr 'R\n' '\n.' < "$file" | 
    sed -n '/^\(ows="[^#][^"]*"\).*/{;s%%'"$file:"'R\1%;p;q;}' 
done 

你tr和sed的可能是與我的不同,所以這可能需要一些適應。

編輯:添加循環,用sed替換grep。