윈 도 우 재질문) setlocal의 지연확장과 call명령을 같이 사용해도 되나요?
2021.12.22 15:02
배치파일에서 setlocal 지연확장(enabledelayedexpansion)과 call 명령을 같이 사용해도 되나요?
다른 글에서 보았는데... 무슨 전역화? 이런거 때문에 안된다고 했던거 같은데 이해를 잘못하겠네요...
그리고 다름이 아니라 이렇게 setlocal 지연확장과 call을 같이 사용하려는 이유는 대략 두가지 때문입니다...
------------------------------------------------
(첫번째 배열)
@echo off
setlocal enabledelayedexpansion
for /f "delims=" %%i in ('dir /b ^|findstr "[^a-z][^0-9].txt"') do (
set /a number+=1
set var[!number!]=%%i
call echo %%var[!number!]%%
)
pause
------------------------------------------------
이처럼 동적으로 변수를 생성하고 해당 변수의 값을 찍으려면 다른 방법도 있겟지만...
이렇게 setlocal 지연확장과 call 명령을 같이 사용하면 좀 더 쉽게 소스작성이 되는거 같아 이렇게 같이 사용해도 된다면 이렇게 사용하고 싶더군요...
또 !변수!와 같은 기능도 지금 소스에서는 배열의 첨자부분에만 사용하지만...
다른 소스에서는 뭐... 배열 인덱스에 쓸 변수말고도 여러 다른 변수를 선언하고 쓸 수도 있으니...
강력한 setlocal 지연확장도 취할 수도 있고...
------------------------------------------------
(두번째 함수)
@echo off
setlocal enabledelayedexpansion
for /f "delims=" %%i in ('dir /b ^|findstr "[^a-z][^0-9].txt"') do (
set /a number+=1
set var[!number!]=%%i
call :lavel
)
goto eof
:lavel
call echo %%var[%number%]%%
exit /b
:eof
pause
------------------------------------------------
함수에 관한 소스는 딱히 call로 라벨을 이동할 필요가 없는 함수긴 하지만...
그냥 전달하고자 하는 것은...
이처럼 setlocal 지연확장을 사용하면서 call (:레이블)로 함수를 타고 싶어서입니다...
예로 call이 아닌 goto로 작성하면...
------------------------------------------------
@echo off
setlocal enabledelayedexpansion
for /f "delims=" %%i in ('dir /b ^|findstr "[^a-z][^0-9].txt"') do (
set /a number+=1
set var[!number!]=%%i
goto :lavel
:endfunction
)
goto eof
:lavel
call echo %%var[%number%]%%
goto endfunction
:eof
pause
------------------------------------------------
")은(는) 예상되지 않았습니다."
라는 오류 문구가 뜨기 때문입니다...
그래서 정리하자면...
setlocal 지연확장과 call을 같이 사용해도 되나요?
안된다면...
어떤 이유때문인지 궁금합니다... (일단 들었던 걸로는 전역화 때문이라는데... 여기에 대한 설명도 해주시면 감사하겠습니다... ㅠ)
댓글 [22]
-
감기걸렸어요... 2021.12.22 15:03 -
지후빠 2021.12.22 16:02
setlocal, call 둘사이 연관성은 없는 것으로 알고 있습니다. (지울수 있게 아랫 글의 댓글은 지웠습니다.)
아마 call로 호출하는 두번째 스크립트에서 변수의 충돌을 막기 위해 setlocal를 사용하라는 내용일 것 같습니다.^^
또... 잘 아시겠지만 함수 호출은 다음 형태처럼 하는 것이 효율적일 것 같습니다. ^^
call :label %%var[!number!]%%
)
goto:eof
:label
echo %1
exit /b
-
감기걸렸어요... 2021.12.22 23:16 값을 찍어보니 알겠습니다...
덕분에 많이 깨닫고 갑니다...
감사합니다...
-
지후빠 2021.12.23 07:04
1) 네 setlocal - endlocal 은 한쌍으로 양파껍질 모양으로 계속 내부에 내부를 지역화해서 바깥쪽 변수는 이어받고 안쪽 변수는 지역화해서 같은 변수명이라도 다른 변수로 인식하게합니다.
2) 2.bat 초반부에 setlocal - 후반부에 endlocal을 사용하면 그 사이에 포함된 변수는 지역화되어서 1.bat 변수와 이름이 같아도 충돌하지 않습니다.
배치파일이 다른가?와는 무관하게 setlocal - endlocal 쌍으로 구분짓고, 괄호와 비슷하다 생각합니다. ((( ))) 대응하는 괄호의 쌍이 범위가 되듯이...
3) for 문 안에 label을 두면 안되는 것으로 알고 있습니다.
-
감기걸렸어요... 2021.12.23 07:54 네 감사합니다...
그렇지 않아도 질문드렸던거랑 또 의문증이 들었던 것들에 대해 하나하나 다 값을 찍어가며 테스트를 해봤더니 깨달았습니다...
덕분에 도움이 많이 됬습니다...
뭔가 많이 알아가네요...
감사합니다...
-
감기걸렸어요... 2021.12.22 23:17 그리고 답변 주셔서 감사합니다...
덕분에 도움 많이 됬습니다...
-
슈머슈마 2021.12.23 00:27
For 문 안쪽에서 변수가 꼬일수 있으니 !! 로 대체한다는 말씀일까요? -
감기걸렸어요... 2021.12.23 00:50 ㅠㅠ;;;
-
슈머슈마 2021.12.23 01:24
어렵네요
뭘 할려는지 잘은 모르겠지만
@echo off
setlocal enabledelayedexpansion
for /f "delims=" %%i in ('dir /b ^|findstr "[^a-z][^0-9].txt"') do (
set /a number+=1
echo [!number!]=%%i
)
endlocal
pause
-
감기걸렸어요... 2021.12.23 02:03 그렇군요...
"For 문 안쪽에서 변수가 꼬일수 있으니 !! 로 대체한다는 말씀일까요?"
이렇게 제글에 달려서 저한테 말한줄 알앗네요...;;;
-
슈머슈마 2021.12.24 00:12
저위에꺼 해봤는데 잘 알진 못하지만 루프 돌리는거 같기도 하고
지후빠님 인자값 %1 을 에코로 출력하는 의미를 잘 모르겠습니다.call 로 밑으로 굳이 내려가는 이유가? 개인적인 생각으로는 정리할때
필요에 따라서 call 로 불러오거나 정리가 필요할때라고 생각합니다.
저위에서는 for문 안에서 충분히 처리 할수 있을거 같은데요
재대로 배우질 못해서 대충 이럴거 같다 라고 생각을
-
감기걸렸어요... 2021.12.24 05:03 그냥 예시용으로 작성한
한글로 된 파일 추출소스입니다
잘 아시겠지만,
예로
1.txt 2.txt 가나다.txt
dir /b |findstr "[^a-z][^0-9].txt"
로 돌려보시면 될듯합니다
-
감기걸렸어요... 2021.12.24 05:17 그리고
set /a number+=1
set var[!number!]=%%i
call echo %%var[!number!]%%
이것은 그냥 배열을 쓰기위함입니다 (배열 ->call echo %%var[!number!]%%)
질문에서도 언급했다 싶이 setlocal의 지연확장과 call 명령을 병행해도 되는지에 대해 묻기 위한 소스입니다
솔직히 위의 소스는 단지 질문을 위한 예시일뿐,
원하는 의도는 그냥 setlocal의 지연확장과 call 명령 병행이라고 보면 될거 같네요,
또 병행을 하려고 하는 이유는,
질문에서도 나와 있다 싶이 배열과 함수를 쓰면서 !변수! 와 같은 setlocal의 기능을 이용하기 위함이라고 보면 될듯합니다
근데
위의 답변에서 상관없다고 말씀하셔서 같이 사용해도 되는거 같네요
-
슈머슈마 2021.12.24 09:21
배열로 쓸수 있나요? 해봤는데 에코 출력이 안되서 그러는데....
-
감기걸렸어요... 2021.12.25 04:38 "배열로 쓸수 있나요? 해봤는데 에코 출력이 안되서 그러는데...."
1.txt*************************
테스트
출력1
출력2
출력3
*****************************@echo offsetlocal enabledelayedexpansionset number=0for /f "delims=" %%i in ('type 1.txt') do (set var[!number!]=%%icall echo !number!:%%var[!number!]%%set /a number+=1)이걸로 돌려보시면 이해되실겁니다 -
감기걸렸어요... 2021.12.24 06:38 제가 함수 타기를 원했기 때문입니다
위의 질문을 보시면
"딱히 call로 라벨을 이동할 필요가 없는 함수긴 하지만...
그냥 전달하고자 하는 것은...
이처럼 setlocal 지연확장을 사용하면서 call로 함수를 타고 싶어서입니다..."
즉, 위의 소스는 어떤 것을 만들겟다고 짠 소스가 아닌 질문을 위한 소스입니다,
그러니까... 이 소스에서는 함수 탈 필요는 없지만, 다른 소스를 짤때는 필요할 수도 있지 않습니까?
그냥 문법에 대해 묻는거라 생각하시면 될 거 같습니다...
아마 이 부분에서 헷갈리셔서 그랬던거 같은데... ㅠㅠ
또 아래의
call :label %%var[!number!]%%
)
goto:eof
:label
echo %1
exit /b
이것에 대해 이해한바를 설명하자면
(call :label %%var[!number!]%%)
매개변수 활용을 추천해주신것으로 알고 있습니다,
아무래도 지문 절약이나 변수대체를 사용 할 수 있으니...
(goto:eof)
위에서 제가 goto eof~:eof 이렇게 이상하게 쓴것을 수정한것
딱히 레이블 필요없이 이렇게 쓰면 파일끝으로 인지하여 배치파일 종료
(echo %1)
여기서는 단순히 받아온 값을 그대로 출력하기에 지문 절약되는거 밖에 의미가 없지만...
예로
echo %~n1
이런식으로 변수대체까지 사용하려면 매개변수로 받는 것이 더 낫지 않겠냐는 의미로 올려주신걸로 알고 있습니다...
-
슈머슈마 2021.12.24 10:57
https://kin.naver.com/qna/detail.naver?d1id=1&dirId=10301&docId=248975521&qb=Y21kIGZvciBza2lw&enc=utf8§ion=kin.ext&rank=1&search_sort=0&spq=0
이런 말씀일까요?
-
감기걸렸어요... 2021.12.24 12:20 네 비슷한거 같습니다
-
슈머슈마 2021.12.24 21:13
저도 질문 하나 있습니다.
배치파일 for 문에서
문자열 출력할때
1
2
3
4
5
6
내용의 텍스트 파일을
3
4
5
라인까지만 출력을 하고 싶은데 방법이 있나요
for “skip=2 tokens=* delims=“ %%a in (list.txt) do (
이후부터 방법을 모르겠음 -
슈머슈마 2021.12.24 21:18
검색을 해봤는데 라인출력은 없는더 같은데 부탁좀 드려도 될까요? -
감기걸렸어요... 2021.12.25 05:56 @echo off
setlocal enabledelayedexpansion
set cnt=0
for /f "skip=2 delims=" %%i in (list.txt) do (
set /a cnt+=1
if !cnt! gtr 3 goto:eof
echo %%i
)
(출력결과)
3
4
5
-
감기걸렸어요... 2021.12.25 17:47 좀더 유연하게 내가 원하는 다른 파일도 이렇게 보고 싶다면
-------------------------------------------------------------------------------------------------------
@ECHO OFF
rem *****************************************************************
rem ***main
setlocal enabledelayedexpansion
set /p path_=검색 경로 지정:
set /p file=테스트 할 파일명 입력:
cls
call :func !path_! !file!
call :func2 %select_file%
endlocal
goto :eof
rem *****************************************************************
rem ***func
:func
setlocal enabledelayedexpansion
set cnt=0
for /f "delims=" %%i in ('dir %1 /s /b ^|findstr %2') do (
set /a cnt+=1
set var[!cnt!]=%%~fi
)
call :func1
endlocal & set select_file=%tmp_%
exit /b
rem *****************************************************************
rem ***func1
:func1
echo 목록-------------------------------------------------------------
for /l %%j in (1,1,!cnt!) do (
call echo [index %%j]:!var[%%j]!
)
echo ------------------------------------------------------------------
echo.
echo.
set /p index=파일 선택 (index 번호로 선택) :
call set tmp_=%%var[!index!]%%
cls
exit /b
rem *****************************************************************
rem ***func2
:func2
setlocal enabledelayedexpansion
echo 선택된 파일----------------------------------------------------
echo %1
echo ------------------------------------------------------------------
set /p skip_line=시작행으로부터 생략할 라인 수 :
set /p line=출력될 라인 수 :
call :func3 %1
endlocal
exit /b
rem *****************************************************************
rem ***func3
:func3
for /f "skip=%skip_line% usebackq delims=" %%i in ("%1") do (
set /a cnt+=1
if !cnt! gtr %line% exit /b
echo %%i
)
-------------------------------------------------------------------------------------------------------
제목이 도중에 잘려서 다시올립니다...