从文件中提取数据以进行比较的更好方法

时间:2012-07-22 12:32:30

标签: bash sed awk diff

问题:比较特定参数的节点的预检查状态和检查后状态的文件。

在社区的帮助下,我编写了以下解决方案,该解决方案从前后目录中的文件中提取信息,并基于“节点ID”(恰好是唯一的,并从文件中提取为好)。从Pre / post文件夹中提取数据后,我已根据node-id和转储文件将文件夹创建到文件夹中。

我的代码提取数据(数据从Pre和Post文件夹中提取)

FILES=$(find postcheck_logs -type f -name *.log)
for f in $FILES
do
    NODE=`cat $f | grep -m 1 ">" | awk '{print $1}' | sed 's/[>]//g'`  ##Generate the node-id
    echo "Extracting Post check information for " $NODE 
    mkdir temp/$NODE-post  ## create a temp directory
    cat $f | awk 'BEGIN { RS=$NODE"> "; } /^param1/ { foo=RS $0; } END { print foo ; }' > temp/$NODE-post/param1.txt ## extract data
    cat $f | awk 'BEGIN { RS=$NODE"> "; } /^param2/ { foo=RS $0; } END { print foo ; }' > temp/$NODE-post/param2.txt
    cat $f | awk 'BEGIN { RS=$NODE"> "; } /^param3/ { foo=RS $0; } END { print foo ; }' > temp/$NODE-post/param3.txt
done

在此之后,我有一个结构:

/Node1-pre/param1.txt
/Node1-post/param1.txt

等等。

现在我很难比较$NODE-pre$NODE-post个文件,

我尝试使用递归grep来做,但我找不到合适的方法。使用diff?

比较这些文件的最佳方法是什么?

而且,我发现上面的数据提取程序非常慢。我认为这不是最好的方式(使用最少的资源)。有什么建议吗?

1 个答案:

答案 0 :(得分:3)

请注意cat one-file的任何实例 - 您可以在管道中的下一个命令上使用I / O重定向。

你可以更简单地完成整个事情:

for f in $(find postcheck_logs -type f -name *.log)
do
    NODE=$(sed '/>/{ s/ .*//; s/>//g; p; q; }' $f)  ##Generate the node-id
    echo "Extracting Post check information for $NODE" 
    mkdir temp/$NODE-post
    awk -v NODE="$NODE" -v DIR="temp/$NODE-post" \
        'BEGIN { RS=NODE"> " }
         /^param1/ { param1 = $0 }
         /^param2/ { param2 = $0 }
         /^param3/ { param3 = $0 }
         END {
             print RS param1 > DIR "/param1.txt"
             print RS param2 > DIR "/param2.txt"
             print RS param3 > DIR "/param3.txt"
             }' $f
done

单个sed命令比cat | grep | awk | sed更好地完成NODE查找过程,您应该计划在任何地方使用$(...)而不是后引号。

日志文件的主要处理应该进行一次;单个awk命令就足够了。该脚本将传递给变量 - NODE和目录名称。 BEGIN被清理干净; NODE之前的$可能不是你想要的。主要行动非常相似;每个都查找相关的参数名称并将其保存在适当的变量中。最后,它将保存的值写入相关文件,用RS的值进行修饰。只有在一行上有多个语句时才需要分号;在这个扩展的脚本中,每行只有一个语句。它看起来比原来大,但这只是因为我使用垂直空间。


至于比较之前和之后的文件,您可以通过多种方式进行,具体取决于您想知道的内容。如果你有一个符合POSIX的diff(你可能会这样做),你可以使用:

diff -r temp/$NODE-pre temp/$NODE-post

报告两个目录内容之间的差异(如果有)。或者,您可以手动执行此操作:

for file in param1.txt param2.txt param3.txt
do
    if cmp -s temp/$NODE-pre/$file temp/$NODE-post/$file
    then : No difference
    else diff temp/$NODE-pre/$file temp/$NODE-post/$file
    fi
done

显然,你可以将它包装在'for each node'循环中。而且,如果您需要这样做,那么您可能希望在变量中捕获find命令的输出(如在原始代码中),这样您就不必重复该操作。