awk:我想使用输入文件名生成一个具有相同名称不同扩展名的输出文件

Awk: I want to use the input filename to generate an output file with same name different extension

我有一个如下所示的脚本:

#! /bin/awk -f

BEGIN { print "start" }
{ print [=10=] }
END { print "end" }

像这样调用脚本:./myscript.awk test.txt

非常简单 - 获取一个文件并在开头添加 "start",在结尾添加 "end"。

现在我想获取输入文件名,我们将其命名为 test.txt,并将输出打印到名为 test.out.

的文件中

所以我尝试打印输入文件名:

BEGIN { print "fname: '" FILENAME "'" }

但是打印出来的是:fname: '' :(

剩下的我想,我有以下内容可以打印到硬编码文件名:

#! /bin/awk -f

BEGIN { print "start" > "test.out" }
{ print [=12=] >> "test.out" }
END { print "end" >> "test.out" }

效果很好。

所以问题是:

  1. 如何获取输入文件名?
  2. 假设我以某种方式在变量中获取输入文件名,例如包含 "test.txt" 的 FILENAME 我将如何制作另一个变量,例如OUTFILE,其中包含 "test.out"?

注意:我会做更多的 awk 处理所以请不要建议使用 sed 或其他语言:))

$ echo 'foo' > ip.txt
$ awk 'NR==1{op=FILENAME; sub(/\.[^.]+$/, ".log", op); print "start" > op}
       {print > op}
       END{print "end" > op}' ip.txt
$ cat ip.log 
start
foo
end

FILENAME 保存到变量,使用 sub 更改扩展名,然后根据需要打印

来自gawk manual

Inside a BEGIN rule, the value of FILENAME is "", because there are no input files being processed yet

尝试这样的事情:

#! /bin/awk -f

BEGIN { 
    file = gensub(".txt",".out","g",ARGV[1])
    print "start" > file
}
{ print [=10=] >> file }
END {
    print "end" >> file
    close(file)
}

我建议在 END{} 语句中也 close() 该文件。很好地打电话给 Sundeep,指出 FILENAME 在 BEGIN 中是空的。

如果您使用的是 GNU awk (gawk),则可以使用模式 BEGINFILEENDFILE

awk 'BEGINFILE{
        outfile=FILENAME; 
        sub(".txt",".out",outfile); 
        print "start" > outfile 
     }
     ENDFILE{
        print "stop" >outfile
     }' file1.txt file2.txt

然后您可以在主 {...} 循环中使用变量 outfile。 这样做将允许您在单个 awk 命令中处理超过 1 个文件。