正在尝试修改awk代码

正在尝试修改awk代码,awk,Awk,以上内容扫描给定目录中的所有文件。打印文件名、每个文件中的行数以及找到的包含“错误”的行数 我现在试图使它,使脚本执行一个命令,如果它读取的任何文件不是一个常规文件。i、 例如,如果文件是gzip文件,则运行特定命令 上面是我尝试将gunzip命令包含在其中并自行完成的。不幸的是,它不起作用。而且,我不能预先“压缩”目录中的所有文件。这是因为并非目录中的所有文件都是“gzip”类型。有些是常规文件 因此,我需要脚本以不同的方式处理任何.gz文件,以便它可以读取、计数和打印其中的行数,以及找到的与

以上内容扫描给定目录中的所有文件。打印文件名、每个文件中的行数以及找到的包含“错误”的行数

我现在试图使它,使脚本执行一个命令,如果它读取的任何文件不是一个常规文件。i、 例如,如果文件是gzip文件,则运行特定命令

上面是我尝试将gunzip命令包含在其中并自行完成的。不幸的是,它不起作用。而且,我不能预先“压缩”目录中的所有文件。这是因为并非目录中的所有文件都是“gzip”类型。有些是常规文件

因此,我需要脚本以不同的方式处理任何.gz文件,以便它可以读取、计数和打印其中的行数,以及找到的与提供的模式匹配的行数(就像该文件是常规文件一样)


有任何帮助吗?

您可以对每个文件执行以下命令:

awk  'BEGIN{OFS=","} FNR == 1
            {if (NR > 1) {print fn,fnr,nl}
                        fn=FILENAME; fnr = 1; nl = 0}
                        {fnr = FNR}
                        /ERROR/ && FILENAME ~ /\.gz$/ {nl++}
                        {
                            cmd="gunzip -cd " FILENAME
                            cmd; close(cmd)
                         }
            END                    {print fn,fnr,nl}
        ' /tmp/appscraps/* > /tmp/test.txt

它将通过打印退出代码0(对于gzip文件)或1(损坏/其他文件)。现在,您可以使用IF来比较输出,以执行所需的处理。

我认为这可能更简单

通过shell扩展,您已经拥有了文件名(因此可以打印它)。 因此,您可以对所有文件执行循环,并对每个文件执行以下操作:

  • 打印文件名
  • zgrep-c ERROR$文件(输出包含“ERROR”的行数)
  • zcat$file | wc-l(这将输出行号)
zgrep和zcat同时处理纯文本文件和gzip文件

假设路径/文件名中没有空格:

用于f in/tmp/appscraps/*
做
n_线=$(zcat“$f”| wc-l)
n_错误=$(zgrep-c错误“$f”)
回显“$f$n_行$n_错误”
完成

这是未经测试的,但应该可以使用。

脚本的这一部分毫无意义:

gunzip -t FILENAME; echo $?
让我对其进行一点重组并对其进行评论,以便更清楚地了解其功能:

        {if (NR > 1) {print fn,fnr,nl}
                    fn=FILENAME; fnr = 1; nl = 0}
                    {fnr = FNR}
                    /ERROR/ && FILENAME ~ /\.gz$/ {nl++}
您还可以使用上面的代码测试以“.gz”结尾的文件名,但是接下来的代码块中的每个文件都将运行gunzip

除此之外,就像其他人建议的那样,只需从壳牌公司打电话给gunzip。awk是一个解析文本的工具,它不是一个调用其他工具的环境——这就是shell的用途

例如,假设您的注释(
打印文件名、每个文件中的行数以及找到的包含“ERROR
”的行数)准确地描述了您希望awk脚本执行的操作,并假设使用awk直接在“.gz”文件中测试“ERROR”一词是有意义的:

{ # for every line of every input file, do the following:

    # If this is the 2nd or subsequent line, print the values of these variables:
    if (NR > 1) {
         print fn,fnr,nl
    } 

    fn = FILENAME    # set fn to FILENAME. Since this will occur for the first line of
                     # every file, this is that value fn will have when printed above,
                     # so why not just get rid of fn and print FILENAME?

    fnr = 1          # set fnr to 1. This is immediately over-written below by
                     # setting it to FNR so this is pointless.

    nl = 0

}
{ # for every line of every input file, also do the following
  # (note the unnecessary "}" then "{" above):

    fnr = FNR        # set fnr to FNR. Since this will occur for the first line of
                     # every file, this is that value fnr will have when printed above,
                     # so why not just get rid of fnr and print FNR-1?
} 

/ERROR/ && FILENAME ~ /\.gz$/ {

    nl++             # increment the value of nl. Since nl is always set to zero above,
                     # this will only ever set it to 1, so why not just set it to 1?
                     # I suspect the real intent is to NOT set it to zero above.

}
更清楚更简单,不是吗

如果直接在“.gz”文件中测试单词ERROR没有意义,那么可以改为:

for file in /tmp/appscraps/*.gz
do
    awk -v OFS=',' '/ERROR/{nl++} END{print FILENAME, NR+0, nl+0}' "$file"
    gunzip -cd "$file"
done > /tmp/test.txt
要处理gz和非gz文件,如您在下面的评论中所述:

for file in /tmp/appscraps/*.gz
do
    zcat "$file" | awk -v file="$file" -v OFS=',' '/ERROR/{nl++} END{print file, NR+0, nl+0}'
    gunzip -cd "$file"
done > /tmp/test.txt

我漏掉了枪拉链,因为从你的要求来看,你不需要它。如果我错了,解释一下你需要它做什么。

术语“常规文件”有技术含义,而
gzip
文件就是常规文件。你的意思是“文本文件”。我相信for不会被带有空格的文件名所困扰,所以你不需要修改IFS。您确实需要引用变量:
“$f”
脚本的目的是扫描给定目录中的所有文件,并输出文件名、文件中的行数以及与字符串匹配的行数。我试图添加关于“gz”文件的部分,因为目录中也有gz文件,而不仅仅是纯文本文件。所以我想解释一下。我尝试了在这篇文章中提出的其他建议,但它们似乎不起作用。我需要每个文件的统计数据…例如。文件名、行数、匹配字符串的行数。这可以通过修改我的原始脚本来实现吗?如果你说“修改我的原始脚本”,你的意思是在一个awk脚本中-是的,但是这将是一个完全混乱的过程,包括系统调用、getline和各种各样的废话,只是为了强迫它以错误的方式获得你想要的输出。我更新了我的答案,以展示如何做我认为你在寻找的事情。
for file in /tmp/appscraps/*
do
    case $file in
        *.gz ) cmd="zcat" ;;
        * )    cmd="cat"  ;;
    esac

    "$cmd" "$file" |
        awk -v file="$file" -v OFS=',' '/ERROR/{nl++} END{print file, NR+0, nl+0}'

done > /tmp/test.txt