-1

我正在编写一个 shell 脚本程序,我在其中内部调用一个 awk 脚本。下面是我的脚本。

for FILE in `eval echo{0..$fileIterator}`
{

if(FILE == $fileIterator)
{
    printindicator =1;
}
    grep RECORD FILEARRAY[FILE]| awk 'for(i=1;i<=NF;i++) {if($i ~ XXXX) {XARRAY[$i]++}} END {if(printIndicator==1){for(element in XARRAY){print element >> FILE B}}'

我希望我对我的代码很清楚。如果您需要任何其他详细信息,请告诉我。

问题

我在这个程序中的动机是遍历所有文件并获取所有文件中具有“XXXX”的行并将这些行存储在一个数组中。这就是我在这里所做的。最后我需要将数组变量的内容存储到一个文件中。我可以在每一步存储内容,如下所示

{if($i ~ XXXX) {XARRAY[$i]++; print XARRAY[$i] >> FILE B}}

但是不采用这种方法的原因是每次我需要执行 I/O 操作,为此花费的时间很多,这就是为什么我每次都将其转换为内存然后最后转储内存数组( XARRAY) 到文件中。

我在这里面临的问题是。shell 脚本每次都调用 awk,数据被存储在数组(XARRAY)中,但对于下一次迭代,XARRAY 的先前内容将被删除,它会放入新内容,因为这假定这是一个新数组。因此,最后当我打印内容时,它只打印最近更新的 XARRAY,而不是预期的所有数据。

预期的建议

1)如何让 awk 脚本意识到 XARRAY 是旧的而不是新的,当它在每次迭代中每次都被调用时。

2) 一种替代方法是每次都进行 I/O。但我对此不感兴趣。除了这个还有其他选择吗。谢谢你。

4

2 回答 2

0

哎呀,不知道它是真实的还是伪代码!

你不能让 awk 保持状态。您要么必须将其保存到临时文件中,要么将其存储在 shell 变量中,将其内容传递给以后的调用。但这对于我理解你想要实现的目标来说太麻烦了。

我建议您省略循环,这将允许您只调用一次 awk 并进行一些重新排序。我假设 FILE A 是循环中的 FILE 而 FILE B 是外部的。重新排序最终会大致如下:

grep RECORD ${FILEARRAY[@]:0:$fileIterator} | awk 'for(i=1;i<=NF;i++) {if($i ~ XXXX) {XARRAY[$i]++}} END {for(element in XARRAY){print element >> FILEB}'

我将文件名扩展移动到grep调用并删除了整个 printIndicator 检查。

这一切都可以更有效地完成(显而易见的是删除grep),但是您提供的细节太少,无法进行早期优化。

编辑:使用更新中的信息修复循环迭代。这是一个循环的解决方案,它不受新的空白问题和太长的命令行的影响:

for FILE in $(seq 0 $fileIterator); do
  grep RECORD "${FILEARRAY[$FILE]}"
done | 
awk 'for(i=1;i<=NF;i++) {if($i ~ XXXX) {XARRAY[$i]++}} END {for(element in XARRAY){print element >> FILEB}'

它仍然awk只运行一次,不断地从循环中提供数据。

如果要将结果加载到数组 UGUGU 中,请执行以下操作(需要 bash 4):

mapfile UGUGU < FILEB
于 2012-07-11T18:35:49.590 回答
0
results=$(for loop | awk{for(element in XARRAY)print element}).. 

我将结果声明为一个数组,因此对于正在打印的每个“元素”,它都应该存储在结果 [1]、结果 [2] 中。

但不是这个,而是执行以下操作......让我们假设 element =“我很好”(for 循环的第一次迭代),element =“你好吗”(for 循环的第二次迭代)。

我的预期结果是 results[1]= "I am fine" 和 results[2] = "How are you" ,但我得到的输出是 results[1]= "I" results[2] =“我”。我不知道为什么它是用空格分隔的..关于这个的任何建议

于 2012-07-11T20:10:49.933 回答