เคล็ดลับสำหรับการเล่นกอล์ฟใน sed


19

คุณมีเคล็ดลับทั่วไปสำหรับการเล่นกอล์ฟในเซดอย่างไร ฉันกำลังมองหาความคิดเห็นที่สามารถนำไปใช้กับปัญหารหัส - กอล์ฟและอย่างน้อยก็ค่อนข้างเฉพาะเจาะจงเพื่อ sed (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ)

กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ


4
ไม่ใช่เคล็ดลับการเล่นกอล์ฟ (แต่ยังเป็นเคล็ดลับสำหรับการเล่นกอล์ฟ): linefeeds ใช้ไบต์มากเท่ากับเซมิโคลอนดังนั้นคุณสามารถทำให้รหัสของคุณสั้นและอ่านง่าย
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 ลักษณะการทำงานนี้จะถูกลบออก :ตอนนี้ต้องใช้ฉลาก
เควิน

แท้จริงแล้วที่นี่ยังเป็นคอมไพล์ที่เกิดขึ้นจริงกระทำการเชื่อมโยง ฉันเดาสำหรับ PPCG สิ่งนี้จะไม่เปลี่ยนแปลงมากนักเนื่องจากเราได้รับอนุญาตให้โพสต์คำตอบสำหรับ GNU sed 4.2.x แต่ก็เป็นเรื่องดีที่รู้ แต่น่าเสียดายที่เคล็ดลับนี้จะไม่ทำงานอย่างเป็นทางการอีกต่อไป
seshoumara

8

เอกสาร GNU sedอธิบายsคำสั่งเป็น"sed ของกองทัพมีดสวิส" แต่ถ้าสิ่งที่คุณต้องการทำคือแทนที่อินสแตนซ์ทั้งหมดของอักขระหนึ่งตัวด้วยyคำสั่งนั้นเป็นสิ่งที่คุณต้องการ:

y/a/b/

หนึ่งตัวอักษรสั้นกว่า:

s/a/b/g

วิธียังเร็วกว่าและสามารถแลกเปลี่ยนตัวอักษรในสถานที่:y/12/21/
mikeserv

6

พิจารณาใช้ไวยากรณ์เพิ่มเติมของ regex (ใน GNU sed) -rตัวเลือกที่มีค่าใช้จ่ายหนึ่งไบต์ในการให้คะแนน แต่ใช้มันเพียงครั้งเดียวที่จะกำจัด backslashes จากคู่\(...\)ได้จ่ายเงินไปแล้วสำหรับตัวเอง


2
ด้วยบันทึกเพิ่มเติมที่-rดูเหมือนว่าsedเฉพาะGNU
จัดการ

@manat - เพิ่มแล้ว (แต่เป็นคำตอบของ Community Wiki ดังนั้นคุณสามารถแก้ไขได้ด้วยตัวเอง)
Toby Speight

แน่นอน. ฉันไม่คิดว่ามันเป็นส่วนหนึ่งของเคล็ดลับมีเพียงบันทึกเพิ่มเติม
จัดการ

และจะช่วยจ่ายสำหรับตัวเองเมื่อใช้+, ?, {}และ|ในการแข่งขัน regex เนื่องจากไม่มีเครื่องหมายที่มีความจำเป็นอย่างใดอย่างหนึ่ง
seshoumara

-Eทำงานเป็นนามแฝง-rในsedการใช้งานหลายอย่างถ้าฉันจำได้อย่างถูกต้อง
phk

6

เมื่อแทนที่เป็นวงซ้ำ ๆ :

loop:
s/foo/bar/g
tloop

โดยทั่วไปไม่จำเป็นต้องแทนที่ทั่วโลกเนื่องจากการวนซ้ำจะแทนที่เหตุการณ์ทั้งหมดในที่สุด:

# GNU sed
:
s/foo/bar/
t

โปรดทราบว่าส่วนขยาย GNU ด้านบน: ป้ายกำกับสามารถมีชื่อว่างได้ช่วยประหยัดไบต์ที่มีค่ามากขึ้น ในการใช้งานอื่น ๆ ป้ายกำกับต้องไม่ว่างเปล่าและกระโดดโดยไม่มีป้ายชื่อจะส่งโฟลว์ไปที่ท้ายสคริปต์ (เช่นเดียวกับn)


1
ชื่อป้ายกำกับที่ว่างเปล่าเป็นเฉพาะ GNU, POSIX ต้องใช้สาขาที่ไม่มีอาร์กิวเมนต์เพื่อข้ามไปยังจุดสิ้นสุดของสคริปต์ (ดูเหมือนจะเป็นพฤติกรรมใน BSDs และ Busybox เช่นกันใน GNU หากคุณไม่เพิ่มที่ว่างเปล่า:)
ninjalj

2
ป้ายกำกับที่ไม่ระบุชื่อมักจะเป็นข้อบกพร่องใน GNU sed ไม่ใช่ส่วนขยายและในเวอร์ชัน 4.3 และสูงกว่าข้อผิดพลาดนี้ได้รับการแก้ไขอย่างน่าเสียดาย ดูที่นี่
seshoumara

5

ไม่มีเลขคณิตในตัว แต่การคำนวณสามารถทำได้ในรูปแบบ unary หรือเป็นทศนิยมแบบ unary-coded รหัสต่อไปนี้แปลงทศนิยมเป็น 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
... และถ้าคุณต้องใช้สิ่งเหล่านี้คุณเกือบจะสูญเสียรหัสกอล์ฟไปแล้วถึงแม้ว่าคุณจะยังคงแข่งขันกับคำตอบของ Java ;-) ยังสนุกกับการใช้งาน
Digital Trauma

การแปลงจาก unary ธรรมดาเป็นทศนิยมให้คำตอบที่ไม่ถูกต้องสำหรับ unary input เทียบเท่ากับรูปแบบ X0X ทศนิยมเช่น 108 บรรทัดที่รับผิดชอบเรื่องนี้คือ/[;v]/!s/\b/0/2สิ่งที่ต้องเปลี่ยนเพื่อ/[;v]/!s:x\+:&0:ให้มันทำงานได้ ดูที่นี่
seshoumara

@seshoumara ดูเหมือนว่าลิงก์ของคุณจะว่างเปล่า แต่เป็นไปได้อย่างมากที่ฉันทำผิดพลาดเมื่อดึงรหัสนั้นออกจากคำตอบอ้างอิงดังนั้นฉันจะใช้การแก้ไขของคุณ
Toby Speight

ลิงก์โหลดอย่างถูกต้อง แต่ฉันคาดหวังว่าจะมีสิ่งอื่นนอกเหนือจากหน้าเทาที่มี "TIO" และสิ่งที่ดูเหมือนโลโก้ Ubuntu - นั่นคือสิ่งที่ตั้งใจหรือไม่ และฉันหมายถึงคำตอบที่สองของคำตอบที่ฉันอ้างอิง ( 58007 ) นั่นคือสิ่งที่กลุ่มตัวอย่างล้วนมาจากกำเนิด
Toby Speight

ลิงก์ TIO ควรมีรหัสที่ถูกต้องรวมทั้งตัวอย่างอินพุต 108 ในนารี ในการรันโค้ดคุณควรเห็นผลลัพธ์ที่ถูกต้อง 108 ไม่ใช่ 180 ดังที่สร้างไว้ก่อนหน้านี้โดยบรรทัดรหัสคงที่ในขณะนี้ การอัปเดตคำตอบที่อ้างอิงนั้นขึ้นอยู่กับคุณทั้งหมด นี่คือวิกิชุมชน
seshoumara

4

ดังที่ได้กล่าวไว้ใน man sed (GNU) คุณสามารถใช้อักขระใด ๆ เป็นตัวคั่นสำหรับนิพจน์ทั่วไปโดยใช้ไวยากรณ์

\%regexp%

%ตัวยึดตำแหน่งอยู่ที่ไหนสำหรับอักขระใด ๆ

สิ่งนี้มีประโยชน์สำหรับคำสั่งเช่น

/^http:\/\//

ซึ่งสั้นกว่า

\%^http://%

สิ่งที่ถูกกล่าวถึงในGNU sed คู่มือแต่ไม่ได้ในman sedคือการที่คุณสามารถเปลี่ยนคั่นของs///และy///ได้เป็นอย่างดี

ตัวอย่างเช่นคำสั่ง

ss/ssg

ลบเครื่องหมายทับทั้งหมดออกจากพื้นที่รูปแบบ


4

หากไม่ได้ถูกห้ามอย่างชัดเจนโดยคำถามฉันทามติสำหรับคำถามเมตานี้ก็คือการป้อนข้อมูลที่เป็นตัวเลขอาจไม่เหมือนกัน วิธีนี้จะช่วยให้คุณได้รับทศนิยม 86 ไบต์ให้เป็นคำตอบเดียวกับคำตอบนี้


นั่นคือฉันทามติ meta สำหรับ sed ที่อ้างถึงรูปแบบ unary แบบเก่าหรือเปล่า? ฉันมีคำตอบหลายข้อที่อินพุตใน UCD จะช่วยฉันในกรณีที่เป็นเช่นนั้น
seshoumara

@seshoumara ฉันหมายถึงเอกไม่ใช่ไม่ใช่ UCD
Digital Trauma

จากนั้นการแปลงจากทศนิยมเป็น unary เก่าจะช่วยให้คุณประหยัด 126 ไบต์ตามคำตอบที่คุณเชื่อมโยง 86 ไบต์สำหรับการแปลงเป็น UCD
seshoumara

4

การขยายตามคำตอบเคล็ดลับนี้เกี่ยวกับการแปลงระหว่างรูปแบบตัวเลขทศนิยมและตัวเลขแบบธรรมดาเรานำเสนอวิธีการทางเลือกต่อไปนี้พร้อมข้อดีและข้อเสีย

ทศนิยมถึงเอกภาพธรรมดา: 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 ไบต์และทำงานพิเศษกับจำนวนเต็มลบเป็นอินพุต

ข้อเสีย: มันเขียนทับพื้นที่ถือ อย่างไรก็ตามเนื่องจากมีความเป็นไปได้สูงที่คุณจะต้องแปลงจำนวนเต็มเข้าในช่วงเริ่มต้นของโปรแกรมข้อ จำกัด นี้จึงไม่ค่อยมีความรู้สึก

ธรรมดาธรรมดาถึงทศนิยม: 102 + 1 (แฟล็ก r) = 103 ไบต์

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

ลองออนไลน์!

ข้อได้เปรียบ: สั้นลง 14 ไบต์ เวลานี้ทั้งรุ่นทิปทำงานสำหรับจำนวนเต็มลบเป็นอินพุต

ข้อเสีย: มันเขียนทับพื้นที่ถือ

สำหรับความท้าทายที่ซับซ้อนคุณจะต้องปรับสนิปเพตเหล่านี้เพื่อทำงานกับข้อมูลอื่น ๆ ที่อาจมีอยู่ในพื้นที่รูปแบบหรือมีพื้นที่ว่างนอกเหนือจากจำนวนที่จะแปลง รหัสสามารถเล่นกอล์ฟได้มากขึ้นถ้าคุณรู้ว่าคุณทำงานกับตัวเลขที่เป็นบวกเท่านั้นหรือว่าเลขศูนย์เพียงอย่างเดียวจะไม่เป็นอินพุต / เอาท์พุตที่ถูกต้อง

ตัวอย่างของคำตอบความท้าทายดังกล่าวที่ผมสร้างขึ้นและใช้ตัวอย่างเหล่านี้เป็นซึ่งกันและกันของจำนวน (1 / x)


s:\n|@$::gสำหรับเอกไปทศนิยมคุณสามารถบันทึกไบต์ที่สองโดยการรวมสองแทนล่าสุด: tio.run/##K05N@f@/2ErX3krNwIpL30G/…
จอร์แดน

ฉันลองเลขทศนิยมเป็นตัวแปลงเอก นี่คือ 97 ไบต์ :) ลองออนไลน์! (เช่นไม่ต้องการ-rแต่ด้วยความเห็นพ้องใหม่ ๆธงไม่นับรวมไปถึง bytecount ต่อไปและมันก็ไม่ได้ทำให้พื้นที่ว่าง)
Kritixi Lithos

ที่จริงถ้าคุณเปลี่ยนบรรทัดสุดท้ายจาก/\n/taเป็น/\n/tคุณบันทึก 1 ไบต์เพื่อรับ 96
Kritixi Lithos

@ Cowquack ขอบคุณ 96 ดีมาก! ไม่มีเวลาตอนนี้จะดูวันหยุดสุดสัปดาห์นี้
seshoumara

แน่นอนว่าจะส่งฉันปิงในการสนทนาแล้ว :)
Kritixi Lithos

3

เรามาพูดถึงคำสั่งtและTคำสั่งต่าง ๆ กันถึงแม้ว่ามันจะถูกอธิบายในหน้า man แต่ก็ง่ายที่จะลืมมันและแนะนำข้อผิดพลาดโดยไม่ได้ตั้งใจโดยเฉพาะเมื่อรหัสมีความซับซ้อน

คำสั่ง Man page สำหรับt:

หาก a s///ได้ทำการทดแทนสำเร็จแล้วตั้งแต่อ่านบรรทัดสุดท้ายและตั้งแต่คำสั่ง t หรือ T ครั้งสุดท้ายให้แตกสาขาเป็นเลเบล

ตัวอย่างแสดงสิ่งที่ฉันหมายถึง:สมมติว่าคุณมีรายการตัวเลขและคุณต้องการนับจำนวนเชิงลบที่มี รหัสบางส่วนด้านล่าง:

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อาจทำให้การตรวจสอบอีกครั้งใน "main" ตกลงไปในกับดักเดียวกัน s/.*/&/;t labelนั่นคือเหตุผลที่ผมมักจะกลับมาจากบล็อกรหัสด้วย มันน่าเกลียด แต่มีประโยชน์


2

แทนที่จะล้างพื้นที่รูปแบบด้วยs/.*//ให้ใช้zคำสั่ง (ตัวพิมพ์เล็ก) หากคุณไปกับ GNU sed นอกเหนือจากจำนวนไบต์ที่ต่ำกว่าก็มีข้อได้เปรียบที่จะไม่เริ่มรอบถัดไปตามคำสั่งdซึ่งจะเป็นประโยชน์ในบางสถานการณ์


1
อาจเป็นประโยชน์เช่นกันหากคุณมีลำดับหลายไบต์ที่ไม่ถูกต้อง (ซึ่งไม่ตรงกัน.)
Toby Speight

2

ฉันรู้ว่านี่เป็นเธรดเก่า แต่ฉันเพิ่งค้นพบทศนิยมที่ซุ่มซ่ามเหล่านั้นไปที่ตัวแปลง UCD ที่มีเกือบร้อยไบต์บางคนถึงกับยุ่งพื้นที่ว่างหรือต้องการsedรุ่นที่ผิดพลาดเป็นพิเศษ

สำหรับ ทศนิยมถึง UCDฉันใช้ (68 ไบต์เป็นโพสต์เก่าที่สุดที่นี่ 87 ไบต์)

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

UCD เป็นทศนิยมคือ (เช่น 66 bytes; โพสต์ที่ดีที่สุดในอดีตที่นี่ 96)

s/$/\n0123456789/
:a      
s/\([0-8]\)x\(.*\n.*\)\1\(.\)/\3\2\1\3/
ta      
P;d
  • \nในการเปลี่ยนไม่ได้พกพา คุณสามารถใช้ตัวอักษรที่แตกต่างกันแทนและบันทึกสองไบต์ แต่คุณจะต้องไบต์ที่จะเอาภาคผนวกแทนมากขึ้นP;d; ดูคำพูดต่อไป หรือถ้าพื้นที่ว่างของคุณว่างเปล่าให้ทำG;s/$/9876543210/โดยไม่มีการลงโทษแบบไบต์
  • หากคุณต้องการการประมวลผลเพิ่มเติมคุณจะต้องมีไบต์เพิ่ม s/\n.*//P;dแทน
  • คุณสามารถบันทึกสองไบต์สำหรับแต่ละsedรุ่นGNU ที่เก่าแก่ได้
  • ไม่คุณไม่สามารถบันทึกแบ็กสแลชทั้งหกเหล่านี้เนื่องจากนิพจน์ทั่วไปที่ขยายเพิ่มนั้นไม่ได้ทำการอ้างอิงซ้ำ

ไม่มีทศนิยมเป็น UCD และตัวแปลงกลับที่โพสต์ในเธรดนี้ที่ทำให้พื้นที่ว่างหรือต้องการรุ่นที่ผิดพลาด
seshoumara

คำตอบของคุณเองตั้งแต่วันที่ 6 เมษายนใช้พื้นที่ทองคำและจะทำงานเฉพาะกับsedรุ่นเก่าที่ละเมิดมาตรฐาน POSIX
Philippos

ฉันไม่ได้แปลงทศนิยมเป็น UCD! อ่านกระทู้อีกครั้งอย่างระมัดระวัง UCD หมายความว่า 12 ถูกแปลงเป็น 0x0xx (สิ่งที่คำตอบของคุณคำนวณ) ในขณะที่เอกภาพธรรมดา (สิ่งที่คำตอบของฉันคำนวณ) หมายความว่า 12 ถูกแปลงเป็น xxxxxxxxxxxx ฉันเลือก @ เป็นสัญลักษณ์ แต่คุณเข้าใจแล้ว และยิ่งกว่านั้นใน PPCG หนึ่งไม่จำเป็นต้องปฏิบัติตามมาตรฐาน POSIX
seshoumara

ถ้าเป็นที่พอใจคุณนายอำเภอ
Philippos

2

อ่านอินพุตทั้งหมดในครั้งเดียวด้วย -z

บ่อยครั้งที่คุณต้องทำงานกับอินพุตทั้งหมดในครั้งเดียวแทนที่จะทีละหนึ่งบรรทัด Nคำสั่งจะเป็นประโยชน์สำหรับว่า:

:
$!{N;b}

... แต่โดยปกติคุณสามารถข้ามมันและใช้-zธงแทน

การ-zตั้งค่าสถานะทำให้ sed ใช้ NUL ( \0) เป็นตัวคั่นบรรทัดอินพุตแทน\nดังนั้นหากคุณรู้ว่าอินพุตของคุณจะไม่มี\0มันจะอ่านอินพุตทั้งหมดพร้อมกันในรูปแบบ“ บรรทัด” เดียว:

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

ลองออนไลน์!


2

เพิ่มบรรทัดใหม่ในหนึ่งไบต์

Gคำสั่งผนวก newline และเนื้อหาของพื้นที่ถือไปยังพื้นที่รูปแบบดังนั้นหากพื้นที่ถือของคุณว่างเปล่าแทนการนี้:

s/$/\n/

คุณสามารถทำได้:

G

ขึ้นบรรทัดใหม่ในสามไบต์

Hคำสั่งผนวก newline และเนื้อหาของพื้นที่รูปแบบไปยังพื้นที่ถือและxแลกเปลี่ยนทั้งสองดังนั้นหากพื้นที่ถือของคุณว่างเปล่าแทนการนี้:

s/^/\n/

คุณสามารถทำได้:

H;x

การทำเช่นนี้จะทำให้พื้นที่ค้างของคุณสกปรกดังนั้นจึงใช้งานได้เพียงครั้งเดียว อย่างไรก็ตามสำหรับอีกสองไบต์คุณสามารถล้างพื้นที่รูปแบบของคุณก่อนทำการสลับซึ่งยังคงประหยัดสองไบต์:

H;z;x

1

ใน 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

regexes ว่างเปล่าเทียบเท่ากับ regex ที่พบก่อนหน้านี้

(ขอบคุณRileyสำหรับการค้นพบสิ่งนี้จากการส่ง anagol )

นี่คือตัวอย่างที่เราได้รับมอบหมายให้สร้าง 100 @วินาทีในบัฟเฟอร์เปล่า

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

โซลูชันที่สองนั้นสั้นกว่า 1 ไบต์และใช้ข้อเท็จจริงที่ว่า regexes ว่างเปล่าจะถูกเติมด้วย regex ที่พบล่าสุด ที่นี่เพื่อทดแทนที่สอง regex ที่ผ่านมา.*ดังนั้น regex .*ที่ว่างเปล่าที่นี่จะเต็มไปด้วย สิ่งนี้ยังทำงานกับ regexes ด้วย/conditionals/ด้วย

โปรดทราบว่านี่เป็นregex ที่พบก่อนหน้านี้ดังนั้นสิ่งต่อไปนี้ก็ใช้ได้เช่นกัน

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

regex ว่างเปล่าเต็มไปด้วย@*แทนที่จะเป็น$เพราะs/$/@/ไม่เคยไปถึง


ใช่คำตอบที่ดี ฉันทำ regexesให้นานขึ้นเพื่อให้สามารถจับคู่ใหม่ได้เช่นนี้ (ทำให้โปรแกรมสั้นลง)
Toby Speight

0

ขั้นตอนที่ไร้ประโยชน์ส่วนใหญ่:

y|A-y|B-z|

สิ่งนี้จะแปลAเป็นBและyไปที่z(... และ-เป็น-;) แต่ไม่มีอะไรอื่นอีกแล้ว

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

จะเพิ่งกลับมา:

Hello world!

คุณสามารถให้แน่ใจว่านี้จะเป็นประโยชน์สำหรับตัวอย่างโดยใช้นี้ค่าเลขฐานสิบหกกรณีที่ต่ำกว่า (ที่มีเพียง0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, eหรือf.)


2
นี่คือสิ่งที่คุณค้นพบวิธีที่ยากหรือไม่! ;-)
Toby Speight

ฉันชอบสคริปที่ไร้ประโยชน์: sed '; ;/s/b;y|A-y|B-z|;s ;s/ //; ; ;' <<<'Hello world'(ทำไมทำอย่างนี้ไม่กด
ทับ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.