需要获取字符串前面的行

时间:2012-11-09 08:57:20

标签: perl batch-file

我有一个文件source.txt,如下所示:

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;

从这个文件中,我需要在sting“执行失败:”之前获取行,并将其放入新文件result.txt中。还有一个条件,如果“执行失败:”之后是“笑错误:或”SHO ERR“我在结果中不需要该文件。上述文件的输出应为:

Executing resource: L:\Core\SQL\smpks_fcj_csdovdmt_addon.sql  
Executing resource: L:\LS\SQL\lnpks_synd_services.sql

请帮忙。 Perl脚本或批处理文件或Ant脚本都可以。

如果我得到一个选项,如果“Sho err”在那里,删除上一行,罚款。

4 个答案:

答案 0 :(得分:2)

这对我有用:

grep -B 1 "Failed" sources.txt  | grep "Executing resource:" > results.txt

编辑:考虑到他“SHO ERR”的要求,可能最好使用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/
     }
   }
 }

你可以像这样使用它:

cat sources.txt | perl script.pl > results.pl

perl script.pl sources.txt > results.pl

答案 1 :(得分:2)

扩展我在Need to copy the lines just before a particular string using batch file找到的原生批量解决方案:

首先使用FINDSTR删除Failed to execute:后跟的所有SHO ERR,并将结果传输到另一个FINDSTR,以保存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

答案 2 :(得分:1)

只是另一个Perl解决方案:

#!/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;

用法与@sergio脚本相同。

答案 3 :(得分:1)

使用tac和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