Linux 如何为处理的每一行向AWK内的命令传递参数

Linux 如何为处理的每一行向AWK内的命令传递参数,linux,parameters,awk,command,gawk,Linux,Parameters,Awk,Command,Gawk,我想将参数$8(文件名)传递给函数“testfunc”。函数应该grep该文件中的一个关键字并返回一年。问题是Linux命令“grep”在fileN中看不到任何内容。如果我直接通过8美元,它仍然看不到任何东西 awk ' function testfunc(fileN, my_year) { "grep 'key_word' fileN" | getline my_year return(my_year) close("grep 'key_word'

我想将参数$8(文件名)传递给函数“testfunc”。函数应该grep该文件中的一个关键字并返回一年。问题是Linux命令“grep”在fileN中看不到任何内容。如果我直接通过8美元,它仍然看不到任何东西

awk '
   function testfunc(fileN, my_year)
     { "grep 'key_word' fileN"  | getline my_year
       return(my_year)
       close("grep 'key_word' fileN")
     }
   BEGIN {OFS="\t"}
         {printf "%s\t%s\t%s\t", $8, testfunc($8), $9}'
试试这个:

function testfunc(fileN)
     { 
       cmd="grep 'key_word' " fileN 
       cmd | getline my_year
       return(sprintf("%s",my_year))
     }

这是您要查找的语法:

awk '
   function testfunc(fileN,       my_year, cmd)
     { cmd = "grep \"key_word\" " fileN
       cmd | getline my_year
       close(cmd)
       return(my_year)
     }
   BEGIN {OFS="\t"}
         {printf "%s\t%s\t%s\t", $8, testfunc($8), $9}'
但正如我在评论中提到的——不要这样做,无论你想做什么,这都是错误的方法

请注意,不能在单引号分隔的脚本中使用单引号

编辑:让我试着澄清我关于使用不同方法的观点。您似乎有一个文件,让我们称它为“file1”,在它的第8个字段中有另一个文件名,在它的第9个字段中有一些您关心的其他值。在第8个字段中命名的所有文件都包含一行,其中包含文本“关键字”,您要打印的是文件1中的第8个字段,然后是选项卡,然后是命名文件中的关键字行,然后是文件1中的第9个字段

这可以写成(只有一种可能的解决方案):

gawk-vofs='\t''
argid
i、 e.在“file1”上调用awk一次,获取包含所需日期信息的文件列表,然后在“file1”之前再次将该文件列表传递给awk,以便最终处理file1时所需的所有信息都存储在数组中

上面使用GNU awk的“nextfile”来提高效率,但这不是必需的,为了清晰起见,使用GNU awk ARGID,但您可以用文件名替换ARGID
有许多替代解决方案,这取决于您真正想做什么……

感谢Ed和Zsolt的帮助。最后,我决定改用shell脚本,因为除了
grep
命令之外,我还需要一个
sed
命令,该命令由于其所需的特殊特性而产生各种各样的问题。因此,我的最终解决方案如下:

fileList=`ls -1 *.xml`
for f in ${fileList} ; do
   my_year=`grep -e "key_word"  ${f} | sed -n '{s/^.*>\([0-9][0-9]*\)<.*$/\1/p}'`
   line=`ls -ltr ${f}`
   line="${line} ${my-year} sthElseHere"
   echo ${line}
done | \

awk ' BEGIN {print "File Name              \tcol02 \tcol03 "
             print "===================    \t====== \t============"}
            {printf "%s\t%s\t%s\n", $8, $4, $9  }'
fileList=`ls-1*.xml`
对于${fileList}中的f;做

my_year=`grep-e“关键字”${f}sed-n'{s/^.*>\([0-9][0-9]*\)您的建议对我部分有效。它确实执行grep,但变量my_year(或系统命令的执行)除外包括我不想要的进位返回,因为它向文件中添加了一个额外的CR。我添加了$9,以便您可以看到$8之后,返回被添加到两行输出记录中。它还添加了一个在第一行输出中找不到的sh:0:命令。实际上,执行的是系统命令在“getline”获取任何内容。“my_year”变量没有获取任何值。换句话说,我看到的输出是系统命令的输出,而不是函数返回的内容。我正在尝试添加
“|tr-d”\n"
但我不知道参数应该在什么地方。这绝对是错误的做法。你试图将awk用作外壳-不要这样做,即使你可以强制它执行并生成你想要的输出,awk也不擅长。惊喜,惊喜,外壳非常擅长。如果你告诉我们你真正想要做的是什么,我们会告诉你可能会有帮助。但是如果您的脚本位于文件中并且是源代码,您可以使用单引号,例如
awk-f yourscript
。非常感谢。这帮助我理解了在单引号脚本中使用单引号的问题。注意:我知道我可以使用纯shell脚本获得类似的输出,但我需要编写更多的脚本用
if
语句编码行。在这种情况下,我所需要的只是更改输入列的顺序,并在它们之间添加一个额外的列。我绝对不是建议在shell中编写整个脚本,我只是建议可能有更好的方法来执行您尝试执行的任何操作,因为有shell调用awk调用shell几乎总是错误的方法,在awk中使用getline充满了危险。我敢打赌,只要采用正确的方法,您在awk中所做的任何事情都是微不足道的。如果您发布另一个带有一些示例输入和预期输出的问题,我相信我们可以帮助您。
fileList=`ls -1 *.xml`
for f in ${fileList} ; do
   my_year=`grep -e "key_word"  ${f} | sed -n '{s/^.*>\([0-9][0-9]*\)<.*$/\1/p}'`
   line=`ls -ltr ${f}`
   line="${line} ${my-year} sthElseHere"
   echo ${line}
done | \

awk ' BEGIN {print "File Name              \tcol02 \tcol03 "
             print "===================    \t====== \t============"}
            {printf "%s\t%s\t%s\n", $8, $4, $9  }'