Linux

zgrep 用於一堆 gz 文件中的多個管道符號

  • May 14, 2020

我的文件夾中有很多 .gz 文件

/a/b/c1.gz
/a/b/c2.gz
/a/b/c3.gz

等等。

一些文件有一個管道分隔符,一些文件有兩個、三個和四個等等,以這種方式:

xyz|abc
xyz|abc|wty
xyz|abc|wty|asd

等等。

如何找到總體上具有兩個管道定界符、總體上具有三個定界符等的所有文件?

讓我們創建三個測試文件:

echo 'xyz|abc' > c1
echo 'xyz|abc|wty' > c2
echo 'xyz|abc|wty|asd' > c3
gzip c*

一行中包含一個管道的文件:

$ zgrep '^[^|]*|[^|]*$' *.gz
c1.gz:xyz|abc

對於任何其他數字(包括一行中的一個管道),您可以使用以下模式:

兩條管道在一條線上:

$ zgrep -E '^([^|]*\|){2}[^|]*$' *.gz
c2.gz:xyz|abc|wty

三個管道在一條線上:

$ zgrep -E '^([^|]*\|){3}[^|]*$' *.gz
c3.gz:xyz|abc|wty|asd

兩根或三根管子排成一行:

$ zgrep -E '^([^|]*\|){2,3}[^|]*$' *.gz
c2.gz:xyz|abc|wty
c3.gz:xyz|abc|wty|asd

最大限度。三個管道排成一行:

$ zgrep -E '^([^|]*\|){,3}[^|]*$' *.gz
c1.gz:xyz|abc
c2.gz:xyz|abc|wty
c3.gz:xyz|abc|wty|asd

如果您只需要文件名,請添加選項-l,即zgrep -lE ...


我的zgrep版本不支持遞歸-r選項。

您可以使用find遞歸搜尋並zgrep在結果上執行:

$ find . -type f -name '*.gz' -exec zgrep -lE '^([^|]*\|){3}[^|]*$' {} \;
./c3.gz

假設在任何給定文件中, -分隔的|列數是恆定的,那麼檢查文件的第一行以確定其中的列數就足夠了。

以下將對名為的文件執行此操作name.gz

gzip -dc name.gz | awk -F '|' -v name="name.gz" '{ print NF, name } { exit }'

因此,通過一個簡單的循環,您將能夠輸出列數和文件名,例如,與模式匹配的所有文件/a/b/c*.gz

for name in /a/b/c*.gz; do
   gzip -dc "$name" |
   awk -F '|' -v name="$name" '{ print NF, name } { exit }'
done

如果您只想輸出具有一定數量列的文件的名稱(n=3例如),則使用

n=3
for name in /a/b/c*.gz; do
   gzip -dc "$name" |
   awk -F '|' -v n="$n" -v name="$name" 'NF == n { print name } { exit }'
done

引用自:https://unix.stackexchange.com/questions/586514