重用变量

重用变量

我折腾了一天还是没有成功。

我有这个脚本:

#!/bin/ksh

fname=$1

for batchname in $(grep -i "Processing batch" $fname | cut -d "'" -f2)
do
Batch_state=`grep -c -i "Batch '$batchname' was successful" $fname`
if [[ "$Batch_state"  -ge 1 ]];then
{
S_Time=`awk '/[0-9]_[0-9].*successful/{getline;getline;getline;print}' $fname | awk '{print $2}'`
E_Time=`awk '/[0-9]_[0-9].*successful/{getline;getline;getline;getline;print}' $fname | awk '{print $2}'`
echo -e $batchname"\t"$S_Time"\t"$E_Time
}
else
{
echo $batchname encountered an error
}
fi
done

此代码产生的输出:

02_1231324      14:29:04 15:29:11   14:32:19 15:33:11
79_3097935      14:29:04 15:29:11   14:32:19 15:33:11

期望的输出:

02_1231324      14:29:04    14:32:19
79_3097935      15:29:11    15:33:11 

输入示例:

2013/06/11 14:29:04 <0999> (725102)
Creating batch '02_1231324.0'...
2013/06/11 14:29:04 <0999> (725102)
Batch '02_1231324' was successful
2013/06/11 14:29:04 <0999> (725102)
TMR:Child ZERO, 160 Docs 320 Pgs 3874 KByts Tot 0.42 WAL 0.10 WALIO 0.15 IO 0.03 secs
2013/06/11 14:29:04 <0999> (725102)  Processing batch '02_1231324'
2013/06/11 14:32:19 <0999> (725102)
Total in batch: 160 documents using 4 KBytes
2013/06/11 15:29:11 <0999> (725102)
Creating batch '79_3097935.0'...
2013/06/11 15:29:11 <0999> (725102)
Batch '79_3097935' was successful
2013/06/11 15:29:11 <0999> (725102)
TMR:Child ZERO, 160 Docs 320 Pgs 3874 KByts Tot 0.42 WAL 0.10 WALIO 0.15 IO 0.03 secs
2013/06/11 15:29:11 <0999> (725102)  Processing batch '79_3097935'
2013/06/11 15:33:11 <0999> (725102)
Total in batch: 160 documents using 4 KBytes
TMR:Child ZERO, 160 Docs 320 Pgs 3874 KByts Tot 0.42 WAL 0.10 WALIO 0.15 IO 0.03 secs
2013/06/11 13:26:57 <0999> (725102)  Processing batch '12_2013162201'
2013/06/11 13:26:57 <0999> (725102)
Total in batch: 160 documents using 4 KBytes

那么,我的脚本有什么问题吗?我怎样才能得到想要的输出?

答案1

您可能需要这样的东西来解析您的日志:

#!/bin/awk -f
{
    if (/was successful/) {
        bn = $2;
        gsub(/'/, "", bn);
        succ[bn] = 1;
    }
    if (/Processing batch/) {
        bn = $7;
        gsub(/'/, "", bn);
        if (bn in succ) {
            succ[bn,",s"] = $2;
            getline
            succ[bn,",e"] = $2;
        } else
            fail[bn] = 1;
    }
}
END {
    for (val in succ)
        if (val !~ /,/)
            print val " " succ[val,",s"] " " succ[val,",e"];
    for (val in fail)
        print val " encountered an error";
}

你原来的剧本轻微地减少到仅1awk在有关输入数据结构的一些严格的1假设 下调用)。

#!/bin/ksh

fname=$1

for batchname in $(grep -i "Processing batch" $fname | cut -d "'" -f2); do
    Batch_state=`grep -c -i "Batch '$batchname' was successful" $fname`
    if [[ "$Batch_state"  -ge 1 ]]; then
        awk -v b=$batchname '
{
    if ($0 ~ "Processing.*" b) {
        s = $2;
        getline;
        e = $2;
        print b " " s " " e;
        exit
    }
}' $fname
    else
        echo $batchname encountered an error
    fi
done

grep -A使用(的较短版本-A是 GNU 扩展,它选择匹配行后面的行数(默认为 1):

#!/bin/ksh

fname=$1

for batchname in $(grep -i "Processing batch" $fname | cut -d "'" -f2); do
    Batch_state=`grep -c -i "Batch '$batchname' was successful" $fname`
    printf "%s" $batchname
    if [[ "$Batch_state"  -ge 1 ]]; then
        grep -A1 "Processing batch '$batchname'" $fname | cut -f2 -d" " | fmt
    else
        printf "encountered an error\n"
    fi
done

但这些仍在处理文件3次。请参阅 ChuckCottrill 的回答了解如何完成。


1似乎批次不是并行处理的,您想要的实际上是包含该行Processing batch及其之后的行。

答案2

该命令会将一行内容赋值给x,(同意)

x=awk '/[0-9]_[0-9].*successful/{getline;getline;getline;print}' log filename | awk '{print $2}'
echo "$x"
2341

您可以处理整个文件三次,但您可以扫描一次,然后提取所需的所有内容。

假设您处理整个文件并计算行数。您使用了 awk,但这是一个 Perl 脚本,只需几行即可完成所有操作,

#!/bin/env perl
use strict;
use warnings;

if( $#ARGV < 0 ) { die "no filename"; }
my ($batchname,$S_Time,$E_Time);
my ($success); #batch successul/failed?
my ($num,$pnum); #linenumber, processing line number
my ($fn,$fh,$line,@cols);

foreach $fn (@ARGV)
{
    if( !open($fh,"<$fn") ) { print "error: cannot open $fn\n"; next; }
    $success=0; $num=0; $pnum=-1; #line number
    while($line = <$fh>)
    {
        if( $line =~ /Batch.*\'([\d_]+)\'.*was successful/ )
        {
            $batchname = $1; $success = 1;
        }
        if( $line =~ /Processing batch \'([\d_]+)\'/ )
        {
            $batchname = $1; $pnum = $num;
        }
        if( $pnum > 0 ) {
        my @cols = split(/\s/,$line);
        if($num==$pnum) { $S_Time=$cols[1]; }
        if($num==$pnum+1) { $E_Time=$cols[1]; }
        }
        $num++;
    }
    if( $success ) { print "$batchname\t$S_Time\t$E_Time\n"; }
    else { print "$batchname encountered an error\n"; }
}

从您提供的示例输入/日志文件中:

2013/06/11 13:26:57 <0999> (725102)
Creating batch '12_2013162201.0'...
2013/06/11 13:26:57 <0999> (725102)
Batch '12_2013162201' was successful
2013/06/11 13:26:57 <0999> (725102)
TMR:Child ZERO, 160 Docs 320 Pgs 3874 KByts Tot 0.42 WAL 0.10 WALIO 0.15 IO 0.03 secs
2013/06/11 13:26:57 <0999> (725102)  Processing batch '12_2013162201'
2013/06/11 13:26:57 <0999> (725102)
Total in batch: 160 documents using 4 KBytes

这是输出,

$ ./extractbatch.pl extractbatch.log 
12_2013162201   13:26:57        13:26:57

这是 awk 版本(首先对 Perl 感到抱歉,我对 awk 有点生疏),

#!/bin/awk -f
BEGIN {
    success=0; batchname="none";
    num=0; pnum=-1;
    S_Time="null"; E_Time="null";
}
#/Batch*was successful/ {
/was successful/ {
    batchname = $2; success = 1;
    printf "1: %s\n",batchname;
}
#/Processing batch */ {
/Processing/ {
    batchname = $7; pnum = num;
    printf "2: %s\n",batchname;
}
{
    if(num==pnum) S_Time=$2;
    if(num==pnum+1) E_Time=$2;
    num++;
}
END {
    if( success>0 ) { printf "%s\t%s\t%s\n",batchname,S_Time,E_Time; }
    else { printf "%s encountered an error\n",batchname; }
}

请注意,perl 版本的功能更多。

答案3

这是有效的,使用与您的脚本相同的基本思想:

#!/bin/ksh

fname=$1
for batchname in $(grep -i "Processing batch" $fname | cut -d "'" -f2)
do
    Batch_state=`grep -c -i "Batch '$batchname' was successful" $fname`
    if [[ "$Batch_state"  -ge 1 ]];then
    S_Time=$(grep "Processing.*$batchname" $fname | awk '{print $2}')
    E_Time=$(grep -A 1 "Processing.*$batchname" $fname | tail -n 1 | awk '{print $2}')
    echo -e "$batchname\t$S_Time\t$E_Time"
else
    echo $batchname encountered an error
fi
done

答案4

您可以unset每次通过 for 循环使用变量。 unset按照罐头上所说的操作,取消设置变量。

-bash-4.2$ export FOO=true
-bash-4.2$ echo $FOO
true
-bash-4.2$ unset FOO
-bash-4.2$ echo $FOO

-bash-4.2$

相关内容