Powershell에서 6번째 파이프를 모두 교체하세요.

Powershell에서 6번째 파이프를 모두 교체하세요.

이미 질문하고 답변한 유사한 질문을 하고 있다는 것을 알고 있지만 정규식과 정규식 엔진이 충분히 다르기 때문에 필요한 답변을 추론할 수 없었습니다. 파이프로 구분되어 있지만 끝점 간에 크게 구분되지는 않는 하드웨어 자산 관리 로그가 있습니다. 로그는 다음과 같습니다.

|STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1|STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2|STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3

내가 하고 싶은 것은 6일마다 |다음과 같이 캐리지 리턴으로 바꾸는 것입니다.

|STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1
|STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2
|STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3

내가 얻은 가장 가까운 것은 각 끝점을 선택하지만 powershell을 사용하여 이를 활용하는 방법을 잘 모르겠습니다.

[^\|]*\|[^\|]*\|[^\|]*\|[^\|]*\|[^\|]*\|[^\|]*

나는 PS의 교체 명령에 익숙하며 최종 결과는 다음과 같을 것이라고 상상합니다.

$hosts = $hosts -replace "<highspeed_low_drag_velcro_snap_regex_here>","\r\n"

미리 감사드립니다!

답변1

좋아요, 사실 이건 좀 까다롭습니다. 틀림없이 정규식은 작업에 가장 적합한 도구는 아니지만 그렇게 할 수 있습니다.

-replace "(?<=^((\|[^|]*){5})+)\|","`n|"

나는 당신에게 그것을 안내하려고 노력할 것입니다:

  • 텍스트에 원하는 섹션이 있습니다.성냥그리고 원하는 섹션바꾸다. 전통적으로 정규식은 전체 검색 문자열을 대체하므로캡처 그룹대체 출력에 복제할 검색 문자열의 일부를 지정합니다. 또 다른 방법은둘러보기, 이것이 제가 여기서 한 일입니다. PowerShell(.NET)은 다음을 지원하는 몇 안 되는 정규식 언어 중 하나입니다.가변 길이 뒤돌아보기, 그래서 우리는 운이 좋았습니다.
  • 섹션은 (?<=)뒤돌아보기입니다. 이는 the =)is 사이의 모든 것을 의미합니다.일치하지만교체됨. 그래서 ^((\|[^|]*){5})+다음과 같이 사용됩니다.상태- 대체는 이 비트가 의도된 대체 이전의 텍스트와 일치하는 경우에만 발생합니다.
  • 섹션은 "줄의 시작 부분( )부터 5개의 s 세트를 일치시킨 다음 텍스트를 다음까지 일치시킵니다 " ^((\|[^|]*){5})*[^|]*로 요약할 수 있습니다 . ^||
    • 줄의 시작은 ^중요합니다. 그렇지 않으면 줄의 어느 곳에서나 일치할 수 있으며 이전에 몇 개의 가 왔는지 보장할 수 없습니다 |.
    • 정규식에서 특별한 의미를 갖기 때문에 |이스케이프해야 합니다 \|. 문자 클래스( ) 내에서는 이스케이프할 필요가 없습니다 [].
    • [^|]*"다음까지의 텍스트"를 의미합니다 . 더 기술적으로는 " 가능한 것 |보다 많은 문자 "를 의미합니다. 더 기술적으로는 " 문자 클래스를 가능한 한 많이 반복합니다. 여기서 해당 문자 클래스는 " 이외의 문자와 일치합니다 .|[^|]|
    • *"가능한 한 많이 이전 문자를 0개 이상 반복함"을 의미합니다.
    • 따라서 다음까지 가능한 한 많은 문자가 (\|[^|]*)일치하는 것을 의미합니다 . 이것은 일치합니다|||text
    • {5}이는 이전 토큰을 정확히 5번 반복한다는 의미입니다. 앞의 토큰을 5번 복사하여 붙여넣는 것과 정확히 같습니다. 그러면 이것이 일치할 것이다|text|text|text|text|text
    • ((\|[^|]*){5})+해당 전체 그룹을 한 번 이상 반복하는 것입니다. 따라서 |text|text|text|text|text, 등을 일치시킬 수 있습니다 . - 5의 배수로 우리가 대신을 |text|text|text|text|text|text|text|text|text|text사용하는 이유는 빈 그룹을 일치시키고 첫 번째 그룹을 바꾸고 싶지 않기 때문입니다 .+*|
    • 그리고 그것은 전체 뒤를 돌아보게 만듭니다. 즉, 라인의 시작부터 |정확히 5 초 뒤에 있는 a를 대체한다는 의미입니다.|
  • 그 다음에는 \|대체할 실제 텍스트로 a를 붙이고 일치하는 뒤돌아보기가 앞에옵니다.
  • 귀하의 예를 들면 |STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1|STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2|STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3다음과 일치합니다.

    |STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1**|**STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2**|**STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3
    

여기에서(아직 하지 않은 경우) 실제로 모든 항목을 교체하려고 한다는 것을 알 수 있습니다.5번째 |첫 번째 빼기, 전부는 아님6번째. 그러나 Lookbehind 메소드는 "첫 번째 마이너스" 상황을 상당히 깔끔하게 처리합니다.


이제 대체 문자열입니다.

  • 이것이 PowerShell이기 때문에 우리가 원할 때 PowerShell 이스케이프 문자가 이기 때문에 \n실제로 원합니다 . 이는 대체 문자열에만 필요하다는 점에 유의하세요. 정규식 자체에서는 해당 리터럴 시퀀스를 정규식 엔진에 전달하는 데 계속 사용됩니다.`n`\n
  • 그리고 모든 줄에 선행이 있으므로 새 줄 뒤에 |새 줄을 추가해야 합니다 . |이는 원래 줄이 a로 끝나지 않기 때문에 작동합니다. |따라서 줄 끝에서 바꿀 것이 없으므로 추가 새 줄이나 후행으로 끝나지 않습니다 |.

보다 전통적인 캡처 그룹 방법을 선호하는 경우:

-replace "((?:[^|]+\|){4}[^|]+)\|","`$1`n|"

이것이 어떻게 작동하는지 파악하는 것은 독자의 연습 문제로 남겨집니다. ;) 팁: $1역참조는 를 사용하여 이스케이프해야 합니다. `그렇지 않으면 PowerShell이 ​​이를 셸 변수로 해석하기 때문입니다.

관련 정보