我正在尝试编写一个awk脚本,在完成任何操作之前告诉用户文件中有多少行。我知道如何在END部分中执行此操作但在BEGIN部分中无法执行此操作。我搜索过SE和Google,但是在END部分或者作为bash脚本的一部分只找到了六种方法,而不是在完成任何处理之前如何做到这一点。我希望得到以下内容:
#!/usr/bin/awk -f
BEGIN{
print "There are a total of " **TOTAL LINES** " lines in this file.\n"
}
{
if($0==4587){print "Found record on line number "NR; exit 0;}
}
但是如果有可能的话,一直无法确定如何做到这一点。感谢。
答案 0 :(得分:5)
您可以阅读该文件两次。
awk 'NR!=1 && FNR==1 {print NR-1} <some more code here>' file{,}
在你的例子中:
awk 'NR!=1 && FNR==1 {print "There are a total of "NR-1" lines in this file.\n"} $0==4587 {print "Found record on line number "NR; exit 0;}' file{,}
您可以使用file file
代替file{,}
(它只是让它出现两次。)
NR!=1 && FNR==1
只有在第二个文件的第一行才会出现这种情况。
使用awk
脚本
#!/usr/bin/awk -f
NR!=1 && FNR==1 {
print "There are a total of "NR-1" lines in this file.\n"
}
$0==4587 {
print "Found record on line number "NR; exit 0
}
awk -f myscript file{,}
答案 1 :(得分:2)
要做到这一点并且对于多个文件,您需要以下内容:
$ cat tst.awk
BEGINFILE {
numLines = 0
while ( (getline line < FILENAME) > 0 ) {
numLines++
}
print "----\nThere are a total of", numLines, "lines in", FILENAME
}
$0==4587 { print "Found record on line number", FNR, "of", FILENAME; nextfile }
$
$ cat file1
a
4587
c
$
$ cat file2
$
$ cat file3
d
e
f
4587
$
$ awk -f tst.awk file1 file2 file3
----
There are a total of 3 lines in file1
Found record on line number 2 of file1
----
There are a total of 0 lines in file2
----
There are a total of 4 lines in file3
Found record on line number 4 of file3
以上使用GNU awk进行BEGINFILE。任何其他解决方案都难以实现,因此它将处理空文件(您需要一个数组来跟踪正在解析的文件,并在跳过空文件后打印FNR==1
和END
部分的信息。
使用getline有一些警告,不应轻易使用,请参阅http://awk.info/?tip/getline,但这是它的适当和强大用途之一。您还可以通过测试ERRNO并跳过文件来测试BEGINFILE中的不可读文件(请参阅gawk手册) - 这种情况会导致其他脚本中止。
答案 2 :(得分:1)
BEGIN {
s="cat your_file.txt|wc -l";
s | getline file_size;
close(s);
print file_size
}
这会将名为your_file.txt
的文件的大小放入awk变量file_size中并将其打印出来。
如果您的文件名是动态的,您可以在命令行上传递文件名并更改脚本以使用该变量。
E.g。 my.awk
BEGIN {
s="cat "VAR"|wc -l";
s | getline file_size;
close(s);
print file_size
}
然后你可以像这样调用它:
awk -v VAR="your_file.txt" -f my.awk
答案 3 :(得分:0)
如果你使用 GNU awk
,需要一个强大的通用解决方案,可以容纳多个,可能是空的输入文件,使用Ed Morton's解决方案。
此答案使用便携式(POSIX兼容)代码。在所提到的限制内,它是健壮的,但Ed的 GNU awk
解决方案更简单,更健壮。
给Ed Morton的帮助提示。
使用 单个输入文件,{strong>更简单,可以使用{{1}中的 shell 命令处理行计数} block ,具有以下优点:
BEGIN
就性能而言,这种方法要么比在awk 'NR==FNR {next} FNR==1 {print NR-1} $0==4587 {print "Found record on line number "NR; exit 0}' file{,}
中读取文件两次稍慢,要么稍快一些,具体取决于所使用的awk
实现:
awk
<强>假设强>:
awk '
BEGIN {
# Execute a shell command to count the lines and read
# result into an awk variable via <cmd> | getline <varname>.
# If the file cannot be read, abort. (The shell has already printed an error msg.)
cmd="wc -l < \"" ARGV[1] "\""; if ((cmd | getline count) < 1) exit 1; close(cmd)
printf "There are a total of %s lines in this file.\n\n", count
}
$0==4587 { print "Found record on line number " NR; exit 0 }
' file
访问。ARGV[1]
字符。以下解决方案涉及 多个文件,并进行类似的假设:
"
等变量赋值。var=value
字符。不难将此概括为处理多个文件,但以下解决方案 不会打印空文件的行数:
"
如果您希望为空文件打印行数,那么事情会变得有点更棘手:
awk '
BEGIN {
# Loop over all input files and store their line counts in an array.
for (i=1; i<ARGC; ++i) {
cmd="wc -l < \"" ARGV[i] "\""; if ((cmd | getline count) < 1) exit 1; close(cmd)
counts[ARGV[i]] = count
}
}
# At the beginning of every (non-empty) file, print the line count.
FNR==1 { printf "There are a total of %s lines in file %s.\n\n", counts[FILENAME], FILENAME }
# $0==4587 { print "%s: Found record on line number %d\n", FILENAME, NR; exit 0 }
' file1 file2 # ...