Linux - 일련의 행에서 여러 패턴을 식별하고 교체

Linux - 일련의 행에서 여러 패턴을 식별하고 교체

입력 내용:

objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson
objectClass: org-abc
objectClass: org-xyz

objectClass: top
objectClass: inetOrgPerson
objectClass: org-abc
objectClass: organizationalPerson
objectClass: person

objectClass: top
objectClass: org-abc
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-xyz

objectClass: top
objectClass: inetOrgPerson
objectClass: org-xyz
objectClass: organizationalPerson
objectClass: person

50MB 크기의 LDIF 파일을 읽습니다.

두 줄 바꿈 사이의 내용은 다음과 같이 처리됩니다.막힌.

  • 이 두 줄(objectClass: org-abc & objectClass: org-xyz)이 임의의 순서로 나타나는 경우막힌그런 다음 BLOCK에서 이 두 줄을 삭제하고 "objectClass: org-111"이라는 새 줄을 추가합니다.

(또는)

  • "objectClass: org-abc" 줄이 단독으로 존재하는 경우막힌해당 줄을 "objectClass: org-222"로 바꾸세요.

(또는)

  • "objectClass: org-xyz" 줄이 단독으로 존재하는 경우막힌해당 줄을 "objectClass: org-333"으로 바꾸세요.

예상 출력:

objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson
objectClass: org-111

objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-222

objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-111

objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-333

Linux 명령(sed 또는 awk)을 사용하여 이러한 출력을 얻거나 더 나은 방법을 제안하려면 어떻게 해야 합니까?

답변1

복잡한AWK해결책:

awk 'function process(a,c) {       # process the lines of one passed block
         for (i=1; i<=c; i++) {    
             split(a[i], fields);  # split the line into 2 fields
             if (fields[2]=="org-abc") abc="222"; 
             else if (fields[2]=="org-xyz") xyz="333"; 
             else print a[i] 
         } 
         if (abc || xyz) printf "objectClass: org-%s\n",(abc && xyz? "111" : (abc? "222":"333")) 
     }
     !NF{ process(a, c); c=abc=xyz=0 }
     { a[++c]=$0 }
     END{ process(a, c) }' file

이것은메모리적절한배열이 a단일 행을 보유하므로 솔루션막힌전체 처리 시간 동안에만. (카운터는 c다음 번에 매번 재설정됩니다.막힌)

산출:

objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson
objectClass: org-111

objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-222

objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-111

objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-333

답변2

이것은 Perl의 "단락 모드"( )의 일반적인 사용 사례입니다. -00여기서 "줄"은 다음과 같이 정의되어 \n\n각 단락이 한 줄로 간주됩니다.

$ perl -00 -lpe 'if(/: org-abc/ && /: org-xyz/){
                    s/(^|\n)[^\n]+: (org-abc|org-xyz)\s*(?=$|\n)//g;
                    s/$/\nobjectClass: org-111/;
                 }
                 else{
                    s/objectClass: org-abc/objectClass: org-222/; 
                    s/objectClass: org-xyz/objectClass: org-333/
                 }' file
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson
objectClass: org-111

objectClass: top
objectClass: inetOrgPerson
objectClass: org-222
objectClass: organizationalPerson
objectClass: person

objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: org-111

objectClass: top
objectClass: inetOrgPerson
objectClass: org-333
objectClass: organizationalPerson
objectClass: person

명확성을 위해 다음은 스크립트로 압축되지 않은 동일한 콘텐츠입니다.

#!/usr/bin/env perl

## Paragraph mode
local $/="\n\n";

my $pat1 = 'objectClass: org-abc';
my $pat2 = 'objectClass: org-xyz';

## Read input file
while (my $line = <>) {
  ## Remove trailing newlines
  chomp($line);

  if($line =~ /$pat1/ && $line=~ /$pat2/){
    $line =~ s/(^|\n)($pat1|pat2)\s*(?=$|\n)//g;
    $line =~ s/$/\nobjectClass: org-111/;
  }
  else{
    $line =~ s/$pat1/objectClass: org-222/;
    $line =~ s/$pat2/objectClass: org-333/
  }
  print "$line\n\n";
}

답변3

또한 쉽습니다 sed:

sed '/^$/!{H;1h;$!d;};x
  /objectClass: org-abc/!{s/\(objectClass: org-\)xyz/\1333/;p;d;}
  s/\(objectClass: org-\)xyz/\1111/;t1
  s/\(objectClass: org-\)abc/\1222/;:b
  :1
  s/\nobjectClass: org-abc//'

첫 번째 줄은 패턴 공간에서 청크를 수집하고 나머지 부분에 대해 확실한 교체를 수행합니다.

관련 정보