데이터 시작 부분에 % 퍼센트 기호가 있는 경우 두 단어 사이에서 데이터를 어떻게 이동할 수 있나요?

데이터 시작 부분에 % 퍼센트 기호가 있는 경우 두 단어 사이에서 데이터를 어떻게 이동할 수 있나요?

다음과 같은 로그 파일이 있습니다.

SWEs-elmPCI-A-01(config)#
 class AutoQoS-VoIP-RTP-Trust
                               ^
% Invalid input detected at '^' marker.

SWEs-elmPCI-A-01(config)#
 class AutoQoS-VoIP-Control-Trust
                               ^
% Invalid input detected at '^' marker.

SWEs-elmPCI-A-01(config)#
 policy-map AutoQoS-Police-CiscoPhone
SWEs-elmPCI-A-01(config-pmap)#

%이제 해시가 포함된 줄 사이에 기호로 시작하는 모든 줄을 찾아 #다른 오류 로그 파일에 넣어야 합니다.

위의 시나리오를 고려한다면 이는 오류 로그 파일에 들어가야 합니다.

   SWEs-elmPCI-A-01(config)#
     class AutoQoS-VoIP-RTP-Trust
                                   ^
    % Invalid input detected at '^' marker.

    SWEs-elmPCI-A-01(config)#
     class AutoQoS-VoIP-Control-Trust
                                   ^
    % Invalid input detected at '^' marker.

    SWEs-elmPCI-A-01(config)#

답변1

이것이 당신이 원하는 것인지 확실하지 않지만 다음과 같습니다.

#!/bin/bash

awk '
BEGIN {
    err=0
}
/^SWE.*#$/ {
    if (err) {
        printf "%s\n%s", txt, $0
        txt=""
        err=0
    } else {
        txt=$0
    }
    next
}
/^% Invalid/ {
    err=1
    txt=txt "\n" $0
    next
}
{
    txt=txt "\n" $0
}
END {
    print ""
}
' "$1"

결과:

SWEs-elmPCI-A-01(config)#
 class AutoQoS-VoIP-RTP-Trust
                               ^
% Invalid input detected at '^' marker.

SWEs-elmPCI-A-01(config)#
 class AutoQoS-VoIP-Control-Trust
                               ^
% Invalid input detected at '^' marker.

SWEs-elmPCI-A-01(config)#

대안으로 내 생각은 그룹화를 위해 추가 행을 사용하는 것입니다.

awk '
BEGIN {
    i = 0
    sep="------------------------------------------------"
}
/^% Invalid/ {
    printf "%s %3d\n%s\n%s\n%s\n",
    sep, ++i, txt, $0, sep
    txt=""
    next
}
/^SWE.*#$/ {

    txt=$0
    next
}
txt != "" {
    txt=txt "\n" $0
}
' "$1"

결과:

------------------------------------------------   1
SWEs-elmPCI-A-01(config)#
 class AutoQoS-VoIP-RTP-Trust
                               ^
% Invalid input detected at '^' marker.
------------------------------------------------
------------------------------------------------   2
SWEs-elmPCI-A-01(config)#
 class AutoQoS-VoIP-Control-Trust
                               ^
% Invalid input detected at '^' marker.
------------------------------------------------

답변2

어쩌면 다음과 같은 것일 수도 있습니다.

sed 'H;/#$/!d;s/^/\
/;x;/\n%/!d;s/.//;x;s/.*//;x'

오류 전후에 프롬프트가 필요하기 때문에 이 프롬프트에는 둘 다 포함되지만 예제 출력과 일치하도록 한 오류 이후와 다음 오류 이전에 나타나는 프롬프트는 포함되지 않습니다.

오류가 서로 이어지는지 여부에 관계없이 두 개의 힌트를 포함하면 훨씬 더 간단해질 것입니다.

sed 'H;/#$/!d;x;/\n%/!d'

오류가 발생하기 전에 힌트를 원하는 경우에도 훨씬 간단합니다.

sed '/#$/!{H;d;}
     x;/\n%/!d'

아마도 이것을 설명하는 가장 좋은 방법은 와 같은 좀 더 장황한 언어로 번역하는 것입니다 perl. 에서 sed홀드 공간은 빈 줄로 초기화된 정적 변수와 같은 반면, 패턴 공간은 sed입력의 각 줄에 차례로 할당되는 변수 입니다. . 그것은 다음과 같습니다:

$hold_space = "\n";
LINE: while ($pattern_space = <>) {

  <sed commands go here>

  print $pattern_space; # unless -n option is passed
}

H명령은 다음과 같이 번역됩니다.

$hold_space .= $pattern_space;

d명령은 다음과 같이 번역됩니다.

next LINE;

즉, 명령 실행을 중지하고 패턴 공간을 버리고 다음 입력 줄부터 다시 시작합니다.

x스왑 모드 및 홀드 공간:

($pattern_space, $hold_space) = ($hold_space, $pattern_space);

따라서 마지막 sed명령은 다음과 같이 변환됩니다.

$hold_space = "\n";
LINE: while ($pattern_space = <>) {

  if (! ($pattern_space =~ /#$/)) { # anything other than a prompt
    $hold_space .= $pattern_space;
    next LINE;
  }

  ($pattern_space, $hold_space) = ($hold_space, $pattern_space);

  if (! ($pattern_space =~ /\n%/)) {
    next LINE;
  }

  print $pattern_space;
}

다음과 같이 더 읽기 쉬운 방식으로 다시 작성할 수 있습니다.

LINE: while ($pattern_space = <>) {

  if ($pattern_space =~ /#$/)) {
    if ($hold_space =~ /\n%/)) {
      print $hold_space;
    }
    $hold_space = $pattern_space;
  } else {
    $hold_space .= $pattern_space;
  }
}

$pattern_space이름을 to $line$hold_spaceto로 바꾸면 $current_block더 명확해집니다.

관련 정보