배치 스크립트를 사용하여 문자열 구문 분석

배치 스크립트를 사용하여 문자열 구문 분석

배치 스크립트를 사용하여 문자열을 어떻게 구문 분석할 수 있나요?

목표는 아래의 모든 항목을 배열에 저장 Import:하고 --> 및 #head와 같이 제거하는 것입니다 .//MPackages/Project/config/abc.txt//Packages/Project/config/cde.txt

테스트.txt:

Version: 4.5.0
Import:
   //MPackages/Project/config/abc.txt                       #head
   //Packages/Project/config/cde.txt                        #head
View:
  //MPackages/Project/config/ac.txt                     #head
  //Packages/Project/config/de.txt                      #head

내 시도:

@echo off

set buildlog="devel.p4inc"

setlocal EnableDelayedExpansion
for /F "tokens=*" %%A in  (devel.p4inc) do  (
  if /i "%%A"=="Import:" set "import=true"
  IF DEFINED import (echo %%A)
)

원하는 출력

   //MPackages/Project/config/abc.txt 
   //Packages/Project/config/cde.txt

가져오기 아래의 모든 항목:

답변1

논리의 주요 문제 중 하나는 무언가가 참인 경우 "가져오기" 변수를 한 번 설정하고 재설정하지 않거나 더 이상 참이 아닌 경우 정의를 해제한다는 것입니다. 따라서 처음 설정된 후에는 루프의 나머지 부분에 대해 "정의된" 상태로 유지됩니다.

내가 선호하는 것은 변수를 구체적으로 설정하는 것입니다( true또는 false). 시작 하도록 설정 false한 다음 원하는 대로 설정 하고 필요할 때 true다시 설정하도록 하세요 . false그런 다음 루프를 반복할 때마다 변수가 방금 정의되었는지 확인하는 대신 True변수 가 구체적으로 설정되었는지 확인합니다.False

이 코드는 귀하의 정보/목표에 따라 작동합니다.

@echo off

setlocal EnableDelayedExpansion

set buildlog=test.txt
set import=false

for /F "tokens=*" %%A in (%buildlog%) do (
    if /i "%%A"=="Import:" (
        set import=true
    )
    if /i "%%A"=="View:" (
        set import=false
    )
    if !import!==true (
        if not "%%A"=="Import:" (
            for /F "tokens=1" %%B in ("%%A") do (
                echo %%B
            )
        )
    )
)

의도적으로 "가져오기" 변수(플래그)를 false시작하도록 설정했습니다.

첫 번째 For 루프는 파일의 각 라인을 통과합니다( test.txt이 예에서는 "buildlog" 변수로 지정됨. 참고: For 루프에서 작동하려면 변수에서 파일 이름 주위의 따옴표를 제거해야 함) .

첫 번째 IF는 현재 줄이 "Import:" 줄인지 확인하고, 그렇다면 "import" 플래그를 로 바꿉니다 true.

다음 IF는 현재 행이 "View:" 행인지 확인하고, 그렇다면 "가져오기" 플래그를 (다시) 로 전환하여 false각 행 처리를 중지합니다.

세 번째 IF는 해당 "import" 플래그가 인지 확인하고 true, 그렇다면 라인을 처리합니다.

그렇다면 true중첩된(4번째) IF는 해당 행이 실제 "import:" 행인지 확인하고, 그렇지 않은 경우 해당 행을 표시합니다(출력에 "Import:" 행이 표시되지 않도록 합니다).

두 번째 For 루프는 표시하려는 라인을 통과하고 원하는 경로인 첫 번째 토큰 세트만 가져오고 #head.

추가/관련 정보:

댓글 후 수정:

"View:" 줄 뒤에 버전 번호가 있는 경우 이를 처리하려면 코드를 다음과 같이 수정할 수 있습니다.

@echo off

setlocal EnableDelayedExpansion

set buildlog=test.txt
set import=false

for /F "tokens=*" %%A in (%buildlog%) do (
    for /F "tokens=1" %%B in ("%%A") do (
        if /i "%%B"=="Import:" (
            set import=true
        )
        if /i "%%B"=="View:" (
            set import=false
        )
        if !import!==true (
            if not "%%B"=="Import:" (
                for /F "tokens=1" %%C in ("%%A") do (
                    echo %%C
                )
            )
        )
    )
)

이렇게 추가된 For 루프는 전체 라인을 확인하는 대신 라인에서 첫 번째 토큰을 가져와 "View:" 또는 "Import:"인지 확인합니다. 검사를 수행하기 위해 라인에서 처음으로 만나는 공백 이후의 모든 항목을 효과적으로 무시합니다.

답변2

@echo off
for /F "usebackq tokens=1" %%A in  ("devel.p4inc") do  (
Set temp=False
if "%%A" == "View:" Goto Exit
if  not "%%A" == "Import:" if  not "%%A" == "Version:"  echo %%A
)
:Exit

답변3

명령줄:

powershell [string]$f=gc test.txt;$pL=$f.IndexOf('Import:')+7;$pR=$f.IndexOf('View:');$s=$f.Substring($pL,$pR-$pL);$s -split'#head'^|ac result.txt

파워셸:

powershell ./parsefl.ps1

parsfl.ps1

[string]$f=gc test.txt;
$pL=$f.IndexOf('Import:')+'Import:'.Length;$pR=$f.IndexOf('View:');
$s=$f.Substring($pL,$pR-$pL);
$s -split'#head'|ac result.txt

관련 정보