배치 골프를위한 팁


14

CMD (Windows Batch)는 코드 골프에 가장 적합한 언어 일 것입니다.

개행 문자를 피하십시오 . 문자와 달리 가장 짧은 코드를 바이트 단위로 찾으려면 불필요한 캐리지 리턴 (줄 바꿈 문자 = 2 바이트)을 모두 제거해야합니다. 이 &작업을 수행하여 각 명령에 대해 1 바이트를 트리밍 할 수 있습니다 .

echo Hello&echo World.

변수 설정 . 스위치를 사용하여 변수를 설정하면 set파서는 공백을 무시합니다.

set /a a+=1
set /p b="User Input: "
:: Will be handled the same as..
set/aa+=1
set/pb="User Input: "

예를 들어 for 루프에는 공백이 필요한 동일한 구문 분석기 규칙이 모든 명령에 적용되지는 않습니다. set, string, or command(즉, 괄호 안에있는 것)과 단어 사이는 제외합니다 do.

for /f %%a in (file.txt)do ...

간단한 수학적 표현 . 또한 set /a명령 에서 증분에 사용한 표현식을 확인하십시오 . 간단한 수학 표현식의 경우 += -= *= /=(예를 들어) 대신 사용하십시오 set /a a=%a%+1.

명령 출력 수집 . 명령의 출력을 얻으려면 때로는 파일을 출력하고 파일에서 읽는 것이 유용 할 수 있습니다. 그렇지 않으면 for 루프를 사용하여 출력을 수집했을 수 있습니다.

for /f %%a in ('echo test') do set a=%%a
:: Can be shortened to
echo test>f&set/pa=<f

echo teststdout을 f라는 파일로 보내고 >f새 명령을 시작한 &다음 파일의 내용을 변수로 가져옵니다 set/pa=<f. 분명히 이것이 항상 유용한 것은 아닙니다. 그러나 필요한 것은 한 줄의 출력 일 때도 가능합니다.

명령 출력 . 명령 출력 @을 억제 할 때는 9 개 이상의 명령 을 억제해야하는 경우가 아니면 명령 시작 전에 사용 하십시오 .이 경우 @echo off스크립트 시작시 사용 하십시오. @echo off는 9 바이트 길이이므로 일반적으로 더 긴 스크립트로 더 많은 바이트를 저장합니다.

명령은 종종 명백한 것 이상 을 수행합니다. 명령이 수행하는 작업에 대해 생각하십시오. 예를 들어; 변수를 설정하고 다른 변수를 에코해야하는 경우 :

set a=OUTPUT
echo %a%
echo test>f
set /p b=<f

/p스위치 와 함께 set 명령을 사용하여 출력 %a%할 수 있습니다.

set a=OUTPUT
echo test>f
set /p b=%a%<f

완전 골프 ...

set a=OUTPUT&echo test>f&set/pb=%a%<f

expamples의 몇 - 모든 숫자의 합계를 계산 - 골드 바흐의 추측 .

다른 팁은 고맙게 생각합니다. 다른 것을 생각하면 계속 업데이트하겠습니다.


16
이 부분의 답변 부분을 질문의 일부가 아닌 답변으로 게시하십시오.
찰스

@Charles 나는 이것이 어떻게했는지에 대해 '팁 질문'에 적합한 형식이라고 확신합니다. 다른 사람들은 자신의 팁으로 답변을 추가 할 수 있습니다.
unclemeat

답변:


4

카운터

당신이 변수가 될 때마다 그에서 시작하는 카운터 역할을합니다 0당신이 쓰기에 할 수 있습니다

set count=0
set/acount+=1

; 그러나 set/a설정되지 않은 변수와 함께 사용될 때마다 그 값은 다음과 같이 가정 되기 때문에 첫 번째 줄을 제거 할 수 있습니다0

set/acounter+=1

코드 블록

코드 블록을 사용해야 할 때 몇 바이트를 줄일 수있는 여러 가지 방법이 있습니다.

코드 블록을 열 때마다 해당 블록의 첫 번째 코드 줄 앞에 줄 바꿈을 삽입하지 않아도됩니다. 닫는 괄호는 자체 줄에있을 필요는 없습니다.

If %a%==%b% (
     echo true
) else (
    echo false
)

골프를 칠 수있다

If %a%==%b% (echo true)else (echo false)

줄 바꿈없이 인쇄

이것에 대한 일반적인 패턴은

echo|set/p=text

하지만, 당신은 2 바이트가 변경 절약 할 수 있습니다 echocd

cd|set/p=text

2
@ ankp-morpork 안녕하세요, 조금 늦었습니다. 그러나 나는 그 if진술이 더 골프화 될 수 있음 을 알려 드리고자합니다 . 가장 좋은 것은 :if %a%==%b% (echo true)else echo false
stevefestl

3

앰퍼샌드

&는 코드를 더 짧게 보이게하지만 줄이 적을수록 줄 바꿈만큼 많은 문자를 사용합니다. 이것은

echo a&echo b

만큼

echo a
echo b

따라서 문자를 낭비하지 않고도 코드를 읽을 수 있습니다.

일부 텍스트 편집기는 줄 바꿈과 캐리지 리턴을 새 줄마다 결합하기 때문에 예외가있을 수 있습니다.


사용하는 모든 텍스트 편집기에서 줄 바꿈이 2 바이트로 계산되므로 원본 게시물에 이것을 포함 시켰습니다. 이 설명을 추가해 주셔서 감사합니다.
unclemeat

2
Window의 carraige 리턴 줄 바꿈은 두 문자이며 많은 텍스트 편집기는 두 문자로 계산하지만 골프 질문에 대답하기 시작했을 때 왼쪽 의견 중 하나는 PPCG 줄 끝이 항상 하나의 문자로 계산된다고 말했습니다.
Jerry Jeremiah

2
유닉스 스타일의 줄 바꿈은 적어도 최신 버전의 Windows에서는 CMD 스크립트에서 잘 작동합니다.
user2428118

1
사실, CMD는 심지어 구문 분석하기 전에 CR 문자를 제거합니다 stackoverflow.com/questions/4094699/...
schnaader

3

숫자 계산 결과를 직접 인쇄

챌린지에서 계산해야하는 숫자를 출력해야하는 경우 다음을 사용할 수 있습니다. cmd/c set/a 을 저장 한 다음 에코하는 대신 계산 결과를 직접 출력하는 데 . 예:

@set/a a=%1+%2
@echo %a%

된다

@cmd/cset/a%1+%2

편집 : 분명히 공백이 필요하지 않으므로 2 바이트가 더 절약됩니다.


2

지연 확장

오래 사용하는 대신 setLocal enableDelayedExpansion사용할 수 있습니다 cmd /v on(또는cmd/von 지연 변수 확장 활성화와 새로운 인터프리터를 시작하는을).

아직 구현하지 않았으므로 예제가 없지만 /c스위치 와 함께 사용할 수 있습니다 . 예:

@cmd/von/cset test=test^&echo !test!

앰퍼샌드 전에 캐럿을 사용하십시오. 여러 앰퍼샌드 또는 다른 특수 문자를 사용해야하는 경우에는 /c스위치 뒤의 모든 것을 따옴표로 묶는 것이 좋습니다 .

@cmd/von/c"set test=test&set test1=test1&echo !test! !test1!"

이 방법은 또한 하나의 @문자 만 사용 하여 모든 입력 을 마스킹 해야하는 이점이 있으므로 (또는 여러 기호)에 /von대한 더 짧은 대안으로 없이 사용할 수 있습니다 .@echo off@

9 자 : @echo off
6 자 :@cmd/c

한 줄로 할 수없는 더 긴 스크립트의 경우 다음을 수행하여 일부 바이트를 저장할 수 있습니다.

@!! 2>nul||cmd/q/v/c%0&&exit/b

또는 골퍼하지 않은 경우 :

@!! 2>nul || cmd /q /v on /c %0 && exit/b

@echo off&setLocal enableDelayedExpansion위의 내용으로 교체하십시오 .

처음 실행할 때 스크립트 !!가 전혀 확장 "!!"되지 않으므로 명령이 아니기 때문에 오류가 발생 합니다. 그런 다음 오류 출력이 nul ( 2>nul) 로 파이프됩니다 . 이 첫 번째 'command'가 실패하면 ( ||), 배치 파일 자체를 호출하는 cmd의 새 인스턴스를 호출합니다 ( /v (on)확장 지연을 활성화하고 /q에코를 끄는 데 사용). 그러면 !!이라는 변수가 없으므로 아무것도 확장되지 않습니다 <NULL>. 그런 다음 나머지 스크립트가 실행됩니다. 그런 다음 cmd의 원래 인스턴스로 돌아가고 ( &&) /b창을 열어 두는 조건으로 종료합니다 (종료하면 첫 번째 cmd 인스턴스의 컨텍스트에서 echo를 사용하여 스크립트를 계속 실행하지 않습니다) 켜고 지연 확장 지연).


이를 위해 배치 파일을 실행하는 cmd /q /v on /c <filename>것은 2 바이트로만 계산해야 -pI합니다. 이는 2 개의 여분 바이트로만 계산되는 Perl 플래그와 비슷한 "플래그"와 유사하기 때문 입니다.
Artyer

1

반복적 인 문자열

변수에 반복 코드 블록을 설정하십시오. 변수를 설정하는 데 사용 된 바이트 수 + 변수를 출력하는 바이트 수가 코드를 직접 호출하는 바이트 수보다 적습니다.

예를 들어, 최대 100을 더하는 조합 그리기를 참조하십시오.

를 포함하는 변수 ( "s"와 같은 하나의 문자로 이름이 지정된)를 만들면 set 명령 사용 당 1 바이트를 저장 set<space>합니다. set 명령을 12 번 이상 사용하는 경우에만 값을 생성합니다. 문자열 끝에 문자가 set s=set있습니다.

set s=set 
%s%a=1
%s%b=2
%s%c=3
%s%d=4
%s%e=5
%s%f=6
%s%g=7
%s%h=8
%s%i=9
%s%j=10
%s%k=11
%s%l=12
%s%m=13

위의 바이트는 1 바이트보다 짧습니다.

set a=1
set b=2
set c=3
set d=4
set e=5
set f=6
set g=7
set h=8
set i=9
set j=10
set k=11
set l=12
set m=13

이것은 아마도 좋지 않은 예일 것입니다.


1

문자열의 시작

표기법 %var:~start,end%은 변수의 하위 문자열을 추출합니다 var. 그러나 start이다 0당신은 완전히 생략 할 수 있습니다. 우리는 이미 당신은 생략 할 수 있다는 것을 알고 ,end당신이 만드는 문자열의 나머지하려는 경우 %var:~%에 거의 쓸모 동의어 %var%가 반환을 제외 ~하면 %var%빈입니다. (아마도 테스트에서 사용할 수 있습니다 : if %var:~%==~?)


나는 마지막 문장이 우리에게 이것을 인용하여 :) +1을 절약 할 것임을 상기시켜줍니다.
stevefestl

1

단축 IF EQU진술

if %a% equ %b% do_something
if %a%==%b% do_something

사용 ==대신하여 equ 저장 3 바이트.


따옴표 단축 IF명세서

이것은 전통적인 소위 "safer"비교 if입니다.

if "%a%"=="%b%" do_something

이 문장을 줄이려면 입력이 영숫자 / 비어 있을 수있을 때 다음을 수행하십시오 .

if %a%.==%b%. do_something

2 바이트 저장


출력이 필요한 과제

질문에 다음과 같은 내용이 나오는 경우 :

하나 이상의 보이는 문자를 출력합니다.

그럼 당신은 이것을 할 수 있습니다 :

cd

cd현재 디렉토리를 보여줍니다 STDOUT.


GOTO라벨링

다음 goto은 바이트를 내림차순으로 정렬 한 레이블 을 작성 하는 몇 가지 방법입니다 .

goto :l
goto l
goto:l

위의 방법은 1 바이트를 저장 합니다.


1
또는 당신이 할 수있는 goto:l같은 1 바이트를 저장하는 하고 그대로 당신의 결장 유지의 추가 보너스가
마테우스 Avellar을

나는 당신의 의견에 따라 내용을 추가 한 : @MatheusAvellar
stevefestl

1

슬래시로 명령과 매개 변수 사이의 공백 생략

정보가없는 제목에 대해 죄송합니다. 내가 얻으려고하는 것은 일부 (전부는 아님) Windows 명령의 경우 매개 변수가 슬래시로 시작하는 한 명령 / 프로그램 이름과 매개 변수 사이의 공백을 생략 할 수 있다는 것입니다. 예를 들면 다음과 같습니다.

for /f %%G in ...

된다

for/f %%G in ...

-1 바이트!

ERRORLEVEL을 사용하는 대신 배관 출력

ERRORLEVEL을 사용하여 명령이 올바르게 실행되었는지 확인하는 것이 가장 짧거나 가장 우아한 방법은 아닙니다. 대신 출력을 파이프 할 수 있습니다. 이것은 다음과 같이 작동합니다 (&& 오퍼레이터가 실행되기 전에 명령이 &&오류없이 실행 된 경우에만 운영자 . ||반면, 운영자 이후의 모든 명령 은 명령이 제대로 실행되지 않은 경우에만 실행됩니다). :

net session>nul
if %errorlevel%==0 (echo 1) else (echo 0)

이것은 다음으로 대체 될 수 있습니다.

net session>nul&&echo 1||echo 0

-26 바이트,와! 다음과 같은 명령에서는 작동하지 않습니다.choice ERRORLEVEL이 일부 입력에 따라 특별한 값을 갖는 곳 .

감사합니다,
Gabe


1

괄호를 효과적으로 사용하기

다시 안녕하세요

두 번째 답변을 게시하여 죄송하지만이 답변이 필요하다고 느꼈습니다. 사람들은 종종 C:\Windows\System32>echo foo각 명령 앞에 성가신 줄 을 표시하지 않고 다음 방법 중 하나를 사용하여 명령 출력을 표시합니다 .
첫 번째 방법 (사용 echo off) :

@echo off
echo foo
echo bar
echo foobar
echo barfoo

두 번째 방법 :

@echo foo
@echo bar
@echo foobar
@echo barfoo

그러나 이러한 방법 중 어느 것도 다음과 같이 짧지 않습니다.

@(echo foo
echo bar
echo foobar
echo barfoo)

아주 편리 하죠? 다른 말로, 이것은 여러 줄의 출력을 파일이나 장치에 쉽게 파이프하는 데 사용될 수 있습니다. 예를 들어이 긴 코드는 다음과 같습니다.

echo foo>file.txt
echo bar>file.txt
echo foobar>file.txt
echo barfoo>file.txt

상당히 짧아집니다 :

(echo foo
echo bar
echo foobar
echo barfoo)>file.txt

이 긴 답변을 읽어 주셔서 감사합니다. 이것이 도움이 되었기를 바랍니다. 감사합니다,
Gabe


질문에 여러 답변을 게시 해도 나쁘지 않습니다.
Outgolfer Erik
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.