sed에서의 골프 팁


19

sed에서 골프를 할 때 어떤 일반적인 팁이 있습니까? 코드 골프 문제에 적용 할 수 있고 적어도 sed에 특정한 아이디어를 찾고 있습니다 (예 : "댓글 제거"는 답이 아닙니다).

답변 당 하나의 팁을 게시하십시오.


4
별로 (하지만 여전히 골프를위한 팁)는 골프 팁 : 당신이 당신의 코드를 짧게 유지할 수 있도록 줄 바꿈, 그냥 세미콜론 많은 바이트로 소비 하고 읽을 수 있습니다.
— Dennis

팁이 아니라 문제 : 나는 GNU sed를 가지고 있지만 F명령은 결코 작동하지 않았습니다. 아무도 이유를 알고 있습니까?
— seshoumara

@seshoumara F는 내 GNU sed (데비안 테스트)에서 작동합니다. -물론 stdin에서 읽는 경우 인쇄 되지만 예상됩니다. 당신은 무엇을 얻 sed -e 'F;Q' /etc/hostname습니까?
— Toby Speight

@TobySpeight이 오류가 발생합니다 : char 1: unknown command: F. 아마도 sed를 업데이트해야합니다. 어떤 버전이 있습니까? L명령은 작동하지 않지만, 이후 쓸모 어쨌든이다 -l n존재한다. GNU sed 사이트에 언급 된 모든 내용이 적용됩니다.
— seshoumara

1
bash, sed and dc이 언어에 대해 이야기하고 질문하고 싶은 모든 사람들을위한 대화방을 열었습니다 . 커뮤니티를 만들어 보자!
— seshoumara

답변:


11

레이블 을 사용해야하는 경우 레이블 이름을 가능한 짧게 만드십시오. 실제로 극단적 인 경우, 빈 문자열을 레이블 이름으로 사용할 수도 있습니다.

:    # define label ""
p    # print pattern space
b    # infinite loop! - branch to label ""

4
gnu sed 4.3에서이 동작은 제거되었습니다 . :이제 라벨이 필요합니다.
— 케빈

실제로 여기에는 실제 git commit link도 있습니다. PPCG의 경우 GNU sed 4.2.x에 대한 답변을 게시 할 수 있기 때문에 많이 변경되지는 않지만 유감 스럽게도이 트릭이 더 이상 공식적으로 작동하지 않는다는 것을 아는 것이 좋습니다.
— seshoumara

8

GNU 나오지 문서는 설명 s등의 명령 "의 sed는 스위스 군용 칼" . 그러나 한 문자의 모든 인스턴스를 다른 문자로 바꾸는 y것만으로도 명령이 필요합니다.

y/a/b/

하나보다 짧은 문자입니다.

s/a/b/g

그것의 방법은 더 빠르고, 문자를 교체 할 수 있습니다 :y/12/21/
— mikeserv

6

GNU 정규식에서 확장 정규식 구문 사용을 고려하십시오. 이 -r옵션은 점수를 매기는 데 1 바이트의 비용이 들지만 한 번만 사용하면 한 쌍의 백 슬래시를 제거하여 \(...\)이미 지불했습니다.


2
-rGNU sed고유 의 추가 메모가 있습니다 .
— manatwork 2016 년

@manat-추가됨 (하지만 커뮤니티 Wiki 답변이므로 직접 편집 할 수 있음).
— Toby Speight

물론이야. 방금 팁의 일부로 간주하지 않고 추가 메모 만 고려했습니다.
— manatwork

그리고 그것은 사용할 때 자체에 대한 지불 계속 +, ?, {}및 |더 백 슬래시가 하나 필요하지 않기 때문에, 정규식 일치한다.
— seshoumara

-E내가 올바르게 기억한다면 -r많은 sed구현 에서 별칭으로 작동 합니다.
— phk

6

루프에서 반복적으로 교체 할 때 :

loop:
s/foo/bar/g
tloop

루프는 결국 모든 발생을 대체하므로 일반적으로 전역으로 대체 할 필요가 없습니다.

# GNU sed
:
s/foo/bar/
t

위의 GNU 확장도 참고하십시오. 레이블은 빈 이름을 가질 수 있으므로 더 소중한 바이트를 절약 할 수 있습니다. 다른 구현에서, 레이블은 비워 둘 수 없으며 레이블없이 점프하면 플로우가 스크립트의 끝으로 이동합니다 (예 :와 동일 n).


1
빈 레이블 이름은 GNU 전용이며 POSIX에는 스크립트의 끝으로 :
— 건너 뛸 인수가없는 분기

2
이름없는 레이블은 항상 확장이 아닌 GNU sed의 버그였으며 버전 4.3 이상에서는이 버그가 수정되었습니다. 여기를 참조 하십시오 .
— seshoumara

5

내장 된 산술은 없지만 계산은 단항 또는 단항 코딩 된 10 진수로 수행 할 수 있습니다. 다음 코드는 10을 UCD로 변환합니다. x는 단위이고 0은 숫자 구분 기호입니다.

s/[1-9]/0&/g
s/[5-9]/4&/g
y/8/4/
s/9/4&/g
s/4/22/g
s/[37]/2x/g
s/[26]/xx/g
s/[1-9]/x/g

다음은 다시 십진수로의 변환입니다.

s/0x/-x/g
s/xx/2/g
y/x/1/
s/22/4/g
s/44/8/g
s/81/9/g
s/42/6/g
s/21/3/g
s/61/7/g
s/41/5/g
s/-//g

이것들은 모두 "숫자를 사용하지 않고 두 개의 곱하기"에 대한 답변 에서 가져 왔습니다 .

평범한 오래된 단항은 이 답변에서이 루프 쌍을 사용하여 "{Curly Numbers};" 로 변환 할 수 있습니다 . 여기서 단위는 ;입니다. 내가 사용했습니다 v및 x위해 로마에 맞게 5하고 10, b"비스"에서 온다.

# unary to decimal
:d
/;/{
s/;;;;;/v/g
s/vv/x/g
/[;v]/!s/x\+/&0/
s/;;/b/g
s/bb/4/
s/b;/3/
s/v;/6/
s/vb/7/
s/v3/8/
s/v4/9/
y/;bvx/125;/
td
}

# Decimal to unary
:u
s/\b9/;8/
s/\b8/;7/
s/\b7/;6/
s/\b6/;5/
s/\b5/;4/
s/\b4/;3/
s/\b3/;2/
s/\b2/;1/
s/\b1/;0/
s/\b0//
/[^;]/s/;/&&&&&&&&&&/g
tu

1
... 그리고 당신이 이것들 중 하나를 사용해야한다면, 당신은 자바 코드와 경쟁 할 수 있지만 코드 골프를 거의 잃어 버릴 것입니다.
— 디지털 외상

일반 단항에서 10 진수로의 변환은 10 진수 형식 X0X에 해당하는 단항 입력에 대해 잘못된 답변을 제공합니다 (예 : 108).이 작업을 수행하는 행은 /[;v]/!s/\b/0/2로 변경 /[;v]/!s:x\+:&0:되어야합니다. 여기를 참조 하십시오 .
— seshoumara

@seshoumara, 귀하의 링크는 빈 페이지 인 것 같습니다. 그러나 참조 된 답변에서 해당 코드를 추출 할 때 오류가 발생한 것은 전적으로 그럴듯합니다. 따라서 수정 사항을 적용합니다.
— Toby Speight

링크가 올바르게로드되지만 "TIO"가있는 회색 페이지 이외의 것이 예상되고 Ubuntu 로고처럼 보이는 것이 예상되는 것입니까? 그리고 나는 평범한 샘플이 시작된 곳에서 내가 언급 한 두 번째 답변 ( 58007 )을 언급하고 있었습니다 .
— Toby Speight

TIO 링크에는 수정 된 코드와 예제 입력 108이 단항으로 포함되어 있어야합니다. 코드를 실행할 때 이전에 수정 된 코드 줄에 의해 이전에 생성 된대로 180이 아닌 올바른 결과 108을 보았을 것입니다. 참조 답변을 업데이트하는 것은 전적으로 귀하에게 달려 있습니다. 이것은 커뮤니티 위키입니다.
— seshoumara

4

man sed(GNU) 에서 언급했듯이 구문을 사용하여 모든 문자를 정규식 구분 기호로 사용할 수 있습니다

\%regexp%

여기서 %모든 문자에 대한 자리 표시 자입니다.

이것은 다음과 같은 명령에 유용합니다

/^http:\/\//

어느 것이 더 짧은

\%^http://%

무엇에 언급 GNU 설명서에 나오지도 하지만, 하지 에있는 것은 man sed당신의 구분 기호를 변경할 수 있다는 것입니다 s///및 y///뿐만 아니라.

예를 들어

ss/ssg

패턴 공간에서 모든 슬래시를 제거합니다.


4

질문에 의해 명시 적으로 금지되지 않은 경우, 이 메타 질문에 대한 합의 는 숫자 입력이 단 항일 수 있다는 것입니다. 이렇게하면 이 답변에 따라 86 바이트의 10 진수가 단항으로 저장됩니다 .


sed에 대한 메타 합의가 일반적인 오래된 단항 형식을 참조하지 않습니까? UCD의 입력이 도움이 될 수있는 몇 가지 대답이 있습니다.
— seshoumara

@seshoumara 내가하지 UCD, 단항 의미
— 디지털 외상

그런 다음 십진수에서 일반 오래된 단항으로 변환하면 연결된 답변에 따라 126 바이트가 절약됩니다. 86 바이트는 UCD로 변환하기위한 것입니다.
— seshoumara 2012

4

이 팁 답변 을 십진수와 일반 단항 형식 간의 변환과 관련하여 확장 하면서 다음과 같은 대체 방법을 장단점으로 제시합니다.

10 진에서 일반 단항으로 : 102 + 1 (r 플래그) = 103 바이트. \t리터럴 탭으로 1 바이트로 계산 했습니다.

h
:
s:\w::2g
y:9876543210:87654321\t :
/ /!s:$:@:
/\s/!t
x;s:-?.::;x
G;s:\s::g
/\w/{s:@:&&&&&&&&&&:g;t}

온라인으로 사용해보십시오!

장점 : 22 바이트 짧고 추가로 음수를 입력으로 사용합니다.

단점 : 보류 공간을 덮어 씁니다. 그러나 프로그램을 시작할 때 입력 정수를 변환해야 할 가능성이 높기 때문에 이러한 제한은 거의 느껴지지 않습니다.

일반 단항에서 10 진수로 : 102 + 1 (r 플래그) = 103 바이트

s:-?:&0:
/@/{:
s:\b9+:0&:
s:.9*@:/&:
h;s:.*/::
y:0123456789:1234567890:
x;s:/.*::
G;s:\n::
s:@::
/@/t}

온라인으로 사용해보십시오!

장점 : 14 바이트 더 짧습니다. 이번에는 두 팁 버전 모두 음수를 입력으로 사용할 수 있습니다.

단점 : 홀드 공간을 덮어 씁니다.

복잡한 문제를 해결하려면이 스 니펫을 수정하여 변환 할 숫자 외에 패턴 공간이나 보유 공간에있을 수있는 다른 정보와 함께 작업해야합니다. 양수로만 작업하거나 0 만 입력이 유효한 입력 / 출력이 아닌 경우 코드를 더 골프화 할 수 있습니다.

이러한 스 니펫을 작성하고 사용한 이러한 챌린지 답변의 예는 숫자 의 역수 (1 / x) 입니다.


단항에서 10 진수의 경우 마지막 두 개의 대체를 결합하여 두 바이트를 절약 할 수 있습니다 s:\n|@$::g. tio.run/##K05N@f@/2ErX3krNwIpL30G/…
— Jordan

나는 십진수를 단항 변환기로 시도했다. 여기에 97 바이트가 있습니다 :) 온라인으로 사용해보십시오! (또한 필요하지는 않지만 -r새로운 합의로 플래그는
— 바이트

실제로 마지막 줄을에서 /\n/ta로 변경 /\n/t하면 1 바이트를 저장하여 96을 얻을 수 있습니다.
— Kritixi Lithos

@Cowsquack 감사합니다, 96 훌륭합니다! 지금 시간이 없어 이번 주말에 살펴볼 것입니다.
— seshoumara

물론, 채팅에 핑을 보내주세요 :)
— Kritixi Lithos

3

tand T명령 에 대해 이야기 해 봅시다 . 맨 페이지에 설명되어 있지만, 특히 코드가 복잡 할 때 잊어 버리고 실수로 버그가 발생하기 쉽습니다.

에 대한 매뉴얼 페이지 설명 t:

s///마지막 입력 행을 읽은 후 마지막 t 또는 T 명령 이후에 a가 성공적인 대체를 수행 한 경우 레이블로 분기하십시오.

의미하는 것을 보여주는 예 : 숫자 목록이 있고 얼마나 많은 음수가 있는지 세고 싶다고합시다. 아래 부분 코드 :

1{x;s/.*/0/;x}                   # initialize the counter to 0 in hold space
s/-/&/                           # check if number is negative
t increment_counter              # if so, jump to 'increment_counter' code block
b                                # else, do nothing (start a next cycle)

:increment_counter
#function code here

괜찮아 보이지만 그렇지 않습니다. 첫 번째 숫자가 양수이면 카운터를 초기화 할 때 t성공적인 s대체 가 있었기 때문에 첫 번째 입력 행에 대한 점프가 수행되기 때문에 해당 코드는 여전히 음수라고 생각합니다 ! 맞습니다 : /-/b increment_counter.

이것이 쉬운 것처럼 보이지만, 함수를 시뮬레이트하기 위해 여러 번 점프를 할 때 여전히 속일 수 있습니다. 이 예에서 increment_counter확실한 코드 블록은 많은 s명령을 사용 합니다. 로 돌아 가면 b main"메인"의 다른 검사가 동일한 트랩에 빠질 수 있습니다. 그래서 나는 보통로 코드 블록에서 돌아온다 s/.*/&/;t label. 추악하지만 유용합니다.


2

GNU sed를 s/.*//사용하는 경우으로 패턴 공간을 지우는 대신 z명령 (소문자)을 사용하십시오 . 적은 바이트 수 외에도 명령 d이 수행하는 것처럼 다음주기를 시작하지 않는 이점이 있으며 , 이는 특정 상황에서 유용 할 수 있습니다.


1
유효하지 않은 멀티 바이트 시퀀스 (와 일치하지 않는 .) 가있는 경우에도 도움이 될 수 있습니다 .
— Toby Speight

2

나는 이것이 오래된 스레드라는 것을 알고 있지만, 거의 백 바이트가있는 서투른 10 진수를 UCD 변환기로 찾았습니다 sed.

들어 UCD에 진수 I 이용 (68 바이트, 전 가장 여기에 게시 87 바이트)

s/$/\n9876543210/
:a
s/\([1-9]\)\(.*\n.*\)\1\(.\)/\3x\2\1\3/
ta
P;d

UCD를 10 진수 로 표시합니다 (66 바이트; 전자는 여기 96으로 게시 됨)

s/$/\n0123456789/
:a      
s/\([0-8]\)x\(.*\n.*\)\1\(.\)/\3\2\1\3/
ta      
P;d
  • \n대체품은 휴대 할 수 없습니다. 대신 다른 문자를 사용하여 2 바이트를 저장할 수 있지만 부록 대신에 부록을 제거하려면 더 많은 바이트가 필요합니다 P;d. 다음 말을 참조하십시오. 또는 보류 공간이 비어 있으면 G;s/$/9876543210/바이트 페널티없이 수행하십시오 .
  • 추가 처리가 필요한 경우 s/\n.*//대신 대신 더 많은 바이트가 필요합니다 P;d.
  • 버그가있는 오래된 GNU sed버전에 대해 각각 2 바이트를 절약 할 수 있습니다
  • 아니요, 확장 정규 표현식이 역 참조를 수행하지 않으므로 6 개의 백 슬래시를 저장할 수 없습니다

이 스레드에는 게시 공간을 어지럽히거나 잘못된 sed 버전이 필요한 UCD 및 백 변환기에 대한 10 진수가 없습니다.
— seshoumara

4 월 6 일의 답변은 골드 스페이스를 사용 sed하며 POSIX 표준을 위반하는 이전 버전 에서만 실행됩니다 .
— Philippos

십진수를 UCD로 변환하지 않습니다! 실을 다시주의해서 읽으십시오. UCD는 12가 0x0xx (답이 계산하는 것)로 변환되는 반면 일반 단항 (응답이 계산하는 것)은 12가 xxxxxxxxxxxx로 변환됨을 의미합니다. @를 기호로 선택했지만 아이디어를 얻습니다. 또한 PPCG에서는 POSIX 표준을 준수 할 필요가 없습니다.
— seshoumara

당신을 기쁘게한다면, 보안관
— Philippos

2

한 번에 전체 입력을 읽습니다. -z

한 번에 한 줄이 아니라 한 번에 전체 입력을 처리해야하는 경우가 종종 있습니다. 이 N명령은 다음에 유용합니다.

:
$!{N;b}

...하지만 일반적으로 건너 뛰고 -z대신 플래그를 사용할 수 있습니다 .

-z플래그는 나오지 사용 NUL을 (만드는 \0대신 입력 라인 구분자로) \n당신이 당신의 입력이 포함되지 않습니다 알고 있다면 그래서 \0, 그것은 한 번에 하나의 "라인"으로의 입력을 모두 읽습니다 :

$ echo 'foo
> bar
> baz' | sed -z '1y/ao/eu/'
fuu
ber
bez

온라인으로 사용해보십시오!


2

1 바이트로 줄 바꿈 추가

이 G명령은 줄 바꿈과 보류 공간의 내용을 패턴 공간에 추가합니다. 따라서 보류 공간이 비어 있으면 다음 대신에 :

s/$/\n/

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

G

3 바이트의 개행을 추가합니다

이 H명령은 줄 바꿈과 패턴 공간의 내용을 보류 공간에 추가하고 x둘을 교체하므로 보류 공간이 비어있는 경우 다음 대신에 다음을 수행하십시오.

s/^/\n/

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

H;x

이것은 보류 공간을 오염 시키므로 한 번만 작동합니다. 그러나 2 바이트가 더 있으면 스왑하기 전에 패턴 공간을 지울 수 있습니다. 이는 여전히 2 바이트를 절약합니다.

H;z;x

1

sed에서 함수에 가장 가까운 것은 레이블입니다. 함수는 코드를 여러 번 실행할 수 있으므로 많은 바이트를 절약 할 수 있기 때문에 유용합니다. 그러나 sed에서는 리턴 레이블을 지정해야하므로 코드 전체에서이 언어를 다른 언어에서와 같이 여러 번 호출 할 수 없습니다.

내가 사용하는 해결 방법은 반환 메모리를 선택하는 데 사용되는 플래그를 두 메모리 중 하나에 추가하는 것입니다. 함수 코드에 단일 메모리 공간 만 필요한 경우에 가장 효과적입니다 (다른 공간).

내가 의미하는 것을 보여주는 예 : 내 프로젝트에서 가져 와서 작은 게임을 sed로 작성

# after applying the player's move, I overwrite the pattern space with the flag "P"
s/.*/P/
b check_game_status
:continue_turn_from_player
#code

b calculate_bot_move
:return_bot_move
# here I call the same function 'check_game_status', but with a different flag: "B"
s/.*/B/
b check_game_status
:continue_turn_from_bot
#code (like say 'b update_screen')

:check_game_status   # this needs just the hold space to run
#code
/^P$/b continue_turn_from_player
/^B$/b continue_turn_from_bot

레이블은 물론 한 글자 만 골라야합니다. 자세한 설명을 위해 전체 이름을 사용했습니다.


1

빈 정규식은 이전에 발생한 정규식과 같습니다.

( 아나 골 제출 에서 이것을 발견 한 Riley 에게 감사드립니다 )

다음은 @빈 버퍼에 100 초 를 만드는 작업을 수행하는 예 입니다.

s/$/@@@@@@@@@@/;s/.*/&&&&&&&&&&/ # 31 bytes
s/.*/@@@@@@@@@@/;s//&&&&&&&&&&/  # 30 bytes

두 번째 솔루션은 1 바이트 짧으며 빈 정규 표현식이 마지막으로 발생한 정규 표현식으로 채워진다는 사실을 사용합니다. 여기에서 두 번째 대체의 경우 마지막 정규식은 .*이므로 빈 정규식은로 채워집니다 .*. 이것은의 정규 표현식에서도 작동합니다 /conditionals/.

이전에 발생한 정규 표현식이므로 다음도 작동합니다.

s/.*/@@@@@@@@@@/;/@*/!s/$/@/;s//&&&&&&&&&&/

빈 정규 표현식은 도달하지 않기 때문에 @*대신 채워집니다 .$s/$/@/


예, 좋은 대답입니다. 나는 정규식을 더 길게 만들어서 이와 같이 다시 일치시킬 수 있도록했습니다 (따라서 프로그램을 더 짧게 만듭니다).
— Toby Speight

0

대부분 쓸모없는 단계 :

y|A-y|B-z|

이 내용은 번역됩니다 A에 B와 y로 z(... 그리고 -에 -)하지만, 아무것도, 그래서

sed -e 'y|A-y|B-z|' <<<'Hello world!'

그냥 돌아올 것이다 :

Hello world!

이 낮은 경우의 16 진수 값에이를 이용하여 샘플, 쓸모가있을 것입니다 보장 수 (만 포함 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e또는 f.)


2
이것은 당신이 어려운 길을 찾은 것입니까?! ;-)
— Toby Speight

쓸모없는 스크립트와 같은 I : sed '; ;/s/b;y|A-y|B-z|;s ;s/ //; ; ;' <<<'Hello world'(왜 그렇게 하지 공간을 억제?)
— F. 하우리
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.