zgrep 用于一堆 gz 文件中的多个管道符号

zgrep 用于一堆 gz 文件中的多个管道符号

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

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

等等。

有些文件有一个管道分隔符,有些有两个、三个和四个等等,如下所示:

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

等等。

如何找到所有具有两个管道分隔符、三个分隔符等的文件?

答案1

假设在任何给定文件中,|- 分隔的列数是恒定的,那么检查文件的第一行就足以确定其中的列数。

以下将对名为 的文件执行此操作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

答案2

让我们创建三个测试文件:

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

答案3

您可以通过管道将文件名传递给 awk 并查找每个文件中 |- 的数量。例如: echo 'A|B|C' |awk -F\| '{打印 NF-1}'

相关内容