하루종일 고생했지만 아직 성공하지 못했습니다.
이 스크립트가 있습니다.
#!/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
입력 데이터의 구조에 대한 일부 엄격한 가정 하에 호출됩니다 .
#!/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$