Reputation:
I have a file source.txt like the following:
Executing resource: L:\Core\SQL\smpks_fcj_csdovdmt_addon.sql
Failed to execute:
Executing resource: L:\LC\SQL\lcpks_lcdtronl_utils.sql
Executing resource: L:\LS\SQL\cspks_adhoc_charge_sch.sql
Failed to execute:
SHO ERR
Executing resource: L:\LS\SQL\gwpks_ls_adhocsch_operations.sql
Executing resource: L:\LS\SQL\lnpks_synd_services.sql
Failed to execute:
Executing resource: L:\LS\SQL\lspks_facility_contracts.sql
Executing resource: L:\LS\SQL\lspks_fcj_lsdpxlog.sql
Executing resource: L:\LS\SQL\lspks_lsdprmnt_kernel.sql
Failed to execute:
sho err;
From this file I need to get the lines just in front of the sting "Failed to execute:" and put it into a new file result.txt. One more condition, if "Failed to execute:" is followed by "sho err: or "SHO ERR" I dont need that file in the result. The output of the above mentioned file should be:
Executing resource: L:\Core\SQL\smpks_fcj_csdovdmt_addon.sql
Executing resource: L:\LS\SQL\lnpks_synd_services.sql
Please help. Perl script or batch file or Ant script is fine.
If I get an option like, if "Sho err" is there, delete the previous line, its fine.
Upvotes: 0
Views: 94
Reputation: 130819
Extending my native batch solution found at Need to copy the lines just before a particular string using batch file:
First use FINDSTR to remove any Failed to execute:
that is followed by SHO ERR
and pipe results to another FINDSTR that saves remaining lines that are followed by Failed to execute:
@echo off
setlocal
::Define LF variable containing a linefeed (0x0A)
set LF=^
::Above 2 blank lines are critical - do not remove
::Define CR variable containing a carriage return (0x0D)
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
setlocal enableDelayedExpansion
::regex "!CR!*!LF!" will match both Unix and Windows style End-Of-Line
findstr /vbric:"Failed to execute:.*!CR!*!LF!SHO ERR" "test.txt" ^
| findstr /ric:"!CR!*!LF!Failed to execute:" >failed.txt
type failed.txt
Upvotes: 2
Reputation: 16974
Using tac and sed:
$ tac file | sed -n -e '/sho err\|SHO ERR/{N;d;}' -e '/Failed to execute/{n;p;}' | tac
Executing resource: L:\Core\SQL\smpks_fcj_csdovdmt_addon.sql
Executing resource: L:\LS\SQL\lnpks_synd_services.sql
Upvotes: 1
Reputation: 57600
Just another Perl solution:
#!/usr/bin/perl
use 5.012; use warnings;
my $last = "";
my $commit_ready = 0;
while (<>) {
if (/^Failed to execute:/) {
$commit_ready = 1;
} else {
print $last if $commit_ready and not /^sho err/i;
$commit_ready = 0;
$last = /^Executing resource: (.*)/ ? $1 : "";
}
}
print $last if $commit_ready;
Usage is the same as with the @sergio script.
Upvotes: 1
Reputation: 69027
This works for me:
grep -B 1 "Failed" sources.txt | grep "Executing resource:" > results.txt
EDIT: to take into account he "SHO ERR" requirement, possibly it is better to use Perl:
my @lines = <>;
push @lines, "";
push @lines, "";
my $linesNum = @lines;
for ( $i = 0; $i < $linesNum - 2; $i++) {
if ($lines[$i+1] =~ /Failed to execute:/) {
if (!($lines[$i+2] =~ /SHO ERR/i)) {
print $lines[$i] if $lines[$i] =~ /^Executing/
}
}
}
you can use it like this:
cat sources.txt | perl script.pl > results.pl
or
perl script.pl sources.txt > results.pl
Upvotes: 2