将参数从shell传递给awk作为数组

时间:2012-07-17 02:42:28

标签: shell awk

我正在使用shell脚本,并且我正在使用awk脚本。我使用awk选项从shell脚本向-v传递参数。在某些时候,当参数大小超过某个限制时,我得到'参数列表太长错误'。这是我之前的问题,但我找到了相同的根本原因。现在我的问题是:

  

使用-v选项从shell传递给awk的变量=太大⟶因此获取参数列表太长错误

我的想法是将大变量分解成小块并将其存储在数组中,然后将数组传递给awk,而不是将单个变量传递给awk

我的问题是:

  • 是否可以将大变量分解为小数组,然后将其传递回awk。我知道如何修改awk脚本中的shell变量。但是如何修改awk脚本中的shell数组呢?

我读到-v选项是不可取的,他们建议管道变量值。如果是那样的话

echo variable | awk '{}' 

因此变量将被传送。但我必须管道一个数组以及其他一些变量。请你帮助我好吗?

 CODE DESCRIPTION
 addvariable=""
 export variable
 loop begins
 eval $(awk -v tempvariable="$addvariable" '{tempvariable=tempvariable+"long string"  variable=tempvariable(Here is where the shell variable(variable) is being modified )}')

  In shell
  addvariable=$variable (Taking the new value of shell variable and feeding back to awk in the next iteration)
   loop ends

所以问题是现在随着add变量和变量不断增加,我得到的参数太长了错误。所以我要做的就是将tempvariable拆分成小块然后将它存储在变量[1]变量中[2]等然后将其分配给addvariable [1],addvariable [2]和feed addvariable [1],[2]而不是整个addvariable作为一个整体。所以我的问题是如何将其作为数组提供。以及如何将awk中的大数据存储到变量[1]变量[2]

CODE     addshellvariable = “”

for i in {0..10}
{
zcat normalfile{i} > FILE A
zcat hugefile{i} > FILE

export shellvariable=""
getdate=grep "XXX" FILE B|sort|Uniq (getdate contains a list of id's)
eval $(awk -v getdata="$getdata" -v addshellvariable="$addshellvariable" BEGIN {tempvariable="";split(addshellvariable,tempshellvariableArray,"*");while(t <= length(tempshellvariable)) {awkarray[tempshellvariableArray[t]];} {for(id in ids) {awkarray[id];} END {for(id in awkarray) {tempvariable=tempvariable"*"id"*"awkarray[id]}  **print "shellvariable"=tempvariable;**}} FILE A)

  addshellvariable=$shellvariable;
}

因为你可以看到awk被嵌入shell中。每次我需要将awkarray内容再次反馈到awk中。这样我就可以获得更新的内容了,这就是我通过打印shell shell变量获取awk数组内容的原因存储在另一个shell变量“addshellvariable”中,并在下一次迭代中被赋予awk。但问题是当shellvariable大小增加某一点然后我得到一个Argument太长的错误。因此,我想要一种解决方案,而不是做 print“shellvariable”= tempvariable; 我可以将其设为 print“shellvariable [1]”= tempvariable的一部分; 等等......

1 个答案:

答案 0 :(得分:3)

您的shell似乎限制了您。我怀疑你的猜测是正确的,这不是一个awk问题,它是你用来调用awk的脚本语言。

您可以使用从文件加载的变量预加载awk。看看这个:

$ printf 'foo=2\nbar=3\nbaz=4\n' > vars
$ printf 'snarf\nblarg\nbaz\nsnurry\n' > text
$ awk 'NR==FNR{split($0,a,"=");vars[a[1]]=a[2];next} $1 in vars {print vars[$1]}' vars text
4
$

这是如何运作的?

前两行printf为我们提供原始数据。如果它们不完全清楚,那么在没有重定向的情况下运行它们(或者生成文件)。

awk脚本有两个主要部分。 Awk脚本包含condition { commands }的重复。在这种情况下,我们有两个这样的集合。

第一组的条件为 NR==FNR 。如果awk正在处理的当前记录号(NR)与当前文件中的当前记录号相同,则评估为“true”。显然,这仅适用于FIRST文件,因为从第二个文件的第一行开始,NR是1加上第一个文件的行数。

在此部分中,我们根据其等号签署split()行,并将数据放入名为vars的数组中。

第二组的条件为 $1 in vars ,如果当前行的第一个单词作为vars数组的下标存在,则计算结果为true。我将此仅作为你可以用变量做的一个例子,因为我不知道你想用这些变量实现什么。

这是否解决了您的问题?如果没有,我们需要查看您的一些代码,以了解如何解决它。


更新评论中的每个建议,这里证明它适用于大变量:

首先,我们准备输入数据:

$ dd if=/dev/random of=out.rand count=128k bs=1k
131072+0 records in
131072+0 records out
134217728 bytes transferred in 3.265765 secs (41098404 bytes/sec)
$ b64encode -o out.b64 out.rand out.rand
$ ls -lh out.b64
-rw-r--r--  1 ghoti  wheel   172M Jul 17 01:08 out.b64
$ awk 'BEGIN{printf("foo=")} NR>1{printf("%s",$0)} END{print ""}' out.b64 > vars
$ ls -lh vars
-rw-r--r--  1 ghoti  wheel   170M Jul 17 01:10 vars
$ wc -l vars
       1 vars
$ cut -c1-30 vars
foo=orq0UgQJyUAcwJV0SenJrSHu3j

好的,我们在一条线上有一个~170MB的变量。我们把它吮吸成awk。

$ awk 'NR==FNR{split($0,a,"=");vars[a[1]]=a[2];next} END{print length(vars["foo"]);print "foo=" substr(vars["foo"],0,26);}' out.var bar
178956971
foo=orq0UgQJyUAcwJV0SenJrSHu3j

我们可以看到变量的大小,前26个字符与我们从shell中看到的匹配。是的,它有效。