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