파일에서 (파일에서 얻은) 문자열을 검색하고 처음 나타나는 문자열의 일부인 다른 문자열의 인스턴스를 바꿉니다.

파일에서 (파일에서 얻은) 문자열을 검색하고 처음 나타나는 문자열의 일부인 다른 문자열의 인스턴스를 바꿉니다.

라이너는 이름: 0602를 검색한 후 다음 이름에 도달할 때까지 Type###의 모든 인스턴스를 유형 700으로 바꿉니다.

sed '/Name: R0602/,/Name.*$/ s/type .*;/type 700;/' file2

이 패드와 비슷한 것을 사용하고 싶지만 file1의 이름 목록을 사용하여 file2를 검색하고 싶습니다. file1 형식의 문자열을 찾으면 이름 부분의 끝에 도달할 때까지 string2의 모든 인스턴스를 바꾼 다음 file1의 다음 줄에 대해 동일한 작업을 수행합니다.

파일 1

Name: 0602
Name: 0603
Name: 0604

파일 2:

# Name: R0601
   Container 4 {
  row 12 type 2 {
     set 1 10 {
         name "C4";
         type 300;
     }
     set 11 20 {
         name "C5";
         type 100;
     }
  set 21 20 {
         name "C6";
         type 300;
     }
  set 31 40 {
         name "C7";
         type 200;
     }
      set 31 40 {
         name "C7";
         type 1200;
     }
  }
}

 # Name: R0602
   Container 5 {
  row 12 type 2 {
     set 1 10 {
         name "C4";
         type 300;
     }
     set 11 20 {
         name "C5";
         type 100;
     }
  set 21 20 {
         name "C6";
         type 300;
     }
  set 31 40 {
         name "C7";
         type 300;
     }
      set 31 40 {
         name "C7";
         type 1100;
     }
  }
}


 # Name: R0603
   Container 6 {
  row 12 type 2 {
     set 1 10 {
         name "C4";
         type 200;
     }
     set 11 20 {
         name "C5";
         type 100;
     }
  set 21 20 {
         name "C6";
         type 300;
     }
  set 31 40 {
        name "C7";
        type 500;
     }
      set 31 40 {
        name "C7";
        type 1100;
     }
  }
}
 # Name: R0604
   Container 6 {
  row 12 type 2 {
     set 1 10 {
         name "C4";
         type 200;
     }
     set 11 20 {
         name "C5";
         type 100;
     }
  set 21 20 {
         name "C6";
         type 300;
     }
  set 31 40 {
        name "C7";
        type 500;
     }
      set 31 40 {
        name "C7";
        type 1100;
     }
  }
}
 # Name: R0605
   Container 6 {
  row 12 type 2 {
     set 1 10 {
         name "C4";
         type 200;
     }
     set 11 20 {
         name "C5";
         type 100;
     }
  set 21 20 {
         name "C6";
         type 300;
     }
  set 31 40 {
        name "C7";
        type 500;
     }
      set 31 40 {
        name "C7";
        type 1100;
     }
  }
}

답변1

짧은 awk 스크립트

awk '
  NR == FNR               { names["R"$2]; next }
  $2 == "Name:"           { replace = ($3 in names) }
  $1 == "type" && replace { sub(/type .*/, "type 700;") }
  1
' file1 file2

NR 및 FNR은 awk 내장 변수입니다. NR은 지금까지 본 총 행 수를 계산합니다. FNR은 현재 파일에서 지금까지 본 줄 수입니다. NR == FNR"첫 번째 데이터 파일에서 작업 중입니다"를 의미하는 awk 관용어입니다. 현재 레코드 수가 총 레코드 수와 동일한 유일한 파일입니다.

따라서 첫 번째 파일을 읽을 때 두 번째 열에 "키"를 저장하려고 합니다. in나중에 사용할 연산자를 고려하면 이를 "이름"의 연관 배열의 키로 저장하는 것이 편리한 장소입니다. 두 번째 파일에 해당 문자가 있으므로 키에 문자 "R"을 추가했습니다.

그 당시 $2 == "Name:"우리는 한 구역의 꼭대기에 있었습니다. 줄의 세 번째 단어가 첫 번째 파일에 나타나면 유형 값을 바꾸려고 합니다. 세 번째 단어가 연관 배열 ($3 in names)의 키로 나타나는지 확인하세요 . names존재하는 경우 첫 번째 단어가 "type"인 후속 줄에서 교체를 수행합니다.

스크립트의 마지막 줄이 흥미롭습니다. 1awk에게 현재 행을 인쇄하도록 지시하는 또 다른 관용적 약어입니다. awk 프로그램은 일련의 condition {action}쌍입니다. 조건이 충족되면 주어진 작업이 수행됩니다. 조건을 생략할 수 있으며, 이 경우 각 행마다 연산이 수행됩니다. 액션 블록 없이 조건이 주어질 수 있으며, 이 경우 기본 액션은 현재 줄을 인쇄하는 것입니다. awk는 빈 문자열과 0을 false로 처리하므로 1조건은 항상 true입니다. 좀 더 장황하게 느껴지면 더 뻔하게 만드는 {print}대신 적어둡니다 .1

답변2

GNU awk 스크립트는 다음과 같습니다:

NR == FNR {
                strt=1
        }
strt == 0 {
                if (match($0,/Name/)) {
                        id=substr($0,RSTART,length($0))
                        id=gensub("R","","g",id)
                }
                file2[id]=file2[id]"\n"$0
        }
 FNR == 1 && NR != 1 {
                 strt=0
                 file2[$0]=""
        }
 strt == 1 {
            file1[$0]=$0
        }
 END {
        for (i in file2) {
                if (file1[i] != "") {
                       resp=gensub(/[[:blank:]]{5}type.*;/,"     type 
700;","g",file2[i])
                       print resp
               }
               else {
                    print file2[i]
               }
       }
}

두 파일을 별도의 배열(파일 1, 파일 2)로 읽습니다(예: "이름: 0603"). 마지막으로 file1과 일치하는 배열 file2를 반복합니다. file1에 항목이 있으면 패턴 일치 및 교체를 위해 gensub를 사용하고, 그렇지 않으면 file2의 항목만 인쇄됩니다.

행동:

 awk -f scriptfile file1 file2

관련 정보