นี่คือคำตอบสั้น ๆ ในนิพจน์แรกจะใช้เครื่องหมายจุลภาคเป็นตัวคั่นดังนั้นการขยายรั้งจึงเป็นเพียงการเชื่อมต่อของนิพจน์ย่อยซ้อนกันสองตัว ในนิพจน์ที่สองคอมมาจะถือว่าเป็นนิพจน์ย่อยอักขระเดียวดังนั้นการแสดงออกของผลิตภัณฑ์จะเกิดขึ้น
สิ่งที่คุณพลาดไปคือนิยามของวิธีการใช้วงเล็บปีกกา นี่คือสามอ้างอิง:
คำอธิบายรายละเอียดเพิ่มเติมดังต่อไปนี้
คุณเปรียบเทียบผลลัพธ์ของนิพจน์นี้:
$ echo {{a..c},{1..3}}
a b c 1 2 3
เป็นผลลัพธ์ของการแสดงออกนี้:
$ echo {a..c},{1..3}
a,1 a,2 a,3 b,1 b,2 b,3 c,1 c,2 c,3
คุณบอกว่านี่เป็นการยากที่จะอธิบายเช่นว่ามันเป็นเคาน์เตอร์ที่ใช้งานง่าย สิ่งที่ขาดหายไปคือคำจำกัดความที่เป็นทางการว่าการประมวลผลส่วนขยายถูกประมวลผลอย่างไร คุณทราบว่าBash Manualไม่ได้ให้คำจำกัดความที่สมบูรณ์
ฉันค้นหาเล็กน้อย แต่ไม่สามารถหาคำจำกัดความที่ขาดหายไป ดังนั้นฉันไปที่รหัสแหล่งที่มา:
แหล่งที่มาประกอบด้วยความเห็นที่เป็นประโยชน์สองสามข้อ อันดับแรกคือภาพรวมระดับสูงของอัลกอริธึมการขยายรั้ง:
Basic idea:
Segregate the text into 3 sections: preamble (stuff before an open brace),
postamble (stuff after the matching close brace) and amble (stuff after
preamble, and before postamble). Expand amble, and then tack on the
expansions to preamble. Expand postamble, and tack on the expansions to
the result so far.
ดังนั้นรูปแบบของโทเค็นการขยายแบบรั้งจึงเป็นดังต่อไปนี้:
<PREAMBLE><AMBLE><POSTAMBLE>
entry-point หลักของการขยายคือฟังก์ชันที่เรียกว่าbrace_expand
ซึ่งอธิบายไว้ดังนี้:
Return an array of strings; the brace expansion of TEXT.
ดังนั้นbrace_expand
ฟังก์ชั่นจะใช้สตริงที่แทนนิพจน์การขยายรั้งและส่งกลับอาร์เรย์ของสตริงที่ขยาย
เมื่อรวมการสังเกตสองข้อนี้เราจะเห็นว่าการขยายกำลังไปยังรายการของสตริงซึ่งแต่ละส่วนเชื่อมต่อกับคำนำ postamble นั้นจะถูกขยายเข้าไปในรายการของสตริงและแต่ละสตริงในรายการ postamble จะถูกรวมเข้ากับแต่ละสตริงในรายการ preamble / amble (เช่นผลิตภัณฑ์ของทั้งสองรายการจะเกิดขึ้น) แต่นี่ไม่ได้อธิบายถึงวิธีการประมวลผลและการ postamble โชคดีที่มีความคิดเห็นอธิบายว่าเป็นเช่นกัน amble ถูกประมวลผลโดยฟังก์ชันที่เรียกว่าexpand_amble
มีคำจำกัดความอยู่ข้างหน้าด้วยความคิดเห็นต่อไปนี้:
Expand the text found inside of braces. We simply try to split the
text at BRACE_ARG_SEPARATORs into separate strings. We then brace
expand each slot which needs it, until there are no more slots which
need it.
ที่อื่นในรหัสเราเห็นว่า BRACE_ARG_SEPARATOR ถูกกำหนดให้เป็นเครื่องหมายจุลภาค สิ่งนี้ทำให้ชัดเจนว่า amble เป็นรายการของสตริงที่คั่นด้วยเครื่องหมายจุลภาคซึ่งบางส่วนอาจเป็นนิพจน์การขยายการรั้งด้วยเช่นกัน สตริงเหล่านี้ในรูปแบบอาร์เรย์เดียว ในที่สุดเราจะเห็นได้ว่าหลังจากexpand_amble
เรียกว่าbrace_expand
ฟังก์ชั่นนั้นเรียกว่าซ้ำใน postamble นี่เป็นคำอธิบายที่สมบูรณ์ของอัลกอริทึม
มีการอ้างอิงอื่น ๆ (ไม่เป็นทางการ) ที่ยืนยันการค้นพบนี้
สำหรับการอ้างอิงหนึ่งตรวจสอบทุบตีแฮกเกอร์วิกิพีเดีย ส่วนของการรวมและการซ้อนไม่ได้ช่วยแก้ไขปัญหาของคุณ แต่หน้าจะให้ไวยากรณ์ / ไวยากรณ์ของการขยายรั้งซึ่งฉันคิดว่าจะตอบคำถามของคุณ ไวยากรณ์ถูกกำหนดโดยรูปแบบต่อไปนี้:
{string1,string2,...,stringN}
{<START>..<END>}
<PREAMBLE>{........}
{........}<POSTSCRIPT>
<PREAMBLE>{........}<POSTSCRIPT>
และการแยกวิเคราะห์อธิบายไว้ดังนี้
การขยายของ Brace ใช้เพื่อสร้างสตริงโดยพลการ สตริงที่ระบุถูกใช้เพื่อสร้างชุดค่าผสมที่เป็นไปได้ทั้งหมดด้วย preambles และ postscripts ที่ล้อมรอบซึ่งเป็นทางเลือก
สำหรับการอ้างอิงอื่นดูที่คู่มือBash Beginner'sซึ่งมีดังต่อไปนี้เพื่อพูดว่า:
Brace expansion is a mechanism by which arbitrary strings may be generated. Patterns to be brace-expanded take the form of an optional PREAMBLE, followed by a series of comma-separated strings between a pair of braces, followed by an optional POSTSCRIPT. The preamble is prefixed to each string contained within the braces, and the postscript is then appended to each resulting string, expanding left to right.
ดังนั้นในการแยกวิเคราะห์การแสดงออกของการขยายรั้งเราไปจากซ้ายไปขวาขยายการแสดงออกแต่ละครั้งและสร้างผลิตภัณฑ์ที่ต่อเนื่อง (ด้วยความเคารพต่อการดำเนินงานของการเรียงสตริง)
ตอนนี้ให้ลองพิจารณาการแสดงออกครั้งแรกของคุณ:
{{a..c},{1..3}}
ในภาษาของ Wiki ของ Bash Hacker สิ่งนี้จะตรงกับรูปแบบแรก:
{string1,string2,...,stringN}
ที่ไหนN=2
,string1={a..c}
และstring2={1..3}
- {<START>..<END>}
ขยายรั้งภายในการดำเนินการครั้งแรกและแต่ละของพวกเขาเป็นอยู่ของแบบฟอร์ม อีกวิธีหนึ่งเราสามารถพูดได้ว่านี่เป็นนิพจน์การขยายแบบรั้งซึ่งประกอบด้วยเพียงความสูงส่ง amble เป็นรายการที่คั่นด้วยเครื่องหมายจุลภาคดังนั้นเราจึงผ่านรายการหนึ่งช่องในแต่ละครั้งและดำเนินการขยายเพิ่มเติมตามที่ต้องการ ไม่มีผลิตภัณฑ์ใดถูกสร้างขึ้นเนื่องจากไม่มีนิพจน์ที่อยู่ติดกัน (ใช้เครื่องหมายจุลภาคเป็นตัวคั่น)
ต่อไปให้ดูที่นิพจน์ที่สองของคุณ:
{a..c},{1..3}
ในภาษาของ Wiki ของ Bash Hacker นิพจน์นี้ตรงกับแบบฟอร์ม:
{........}<POSTSCRIPT>
ที่ลงท้ายเป็น ,{1..3}
sub-แสดงออก อีกวิธีหนึ่งเราสามารถพูดได้ว่าการแสดงออกนี้มีความ{a..c}
ถ่อมใจ ( ,{1..3}
) และ postamble ( ) การเดินทอดน่องถูกขยายไปยังรายการa b c
และจากนั้นเชื่อมโยงแต่ละรายการเหล่านี้เข้าด้วยกันกับแต่ละสายอักขระในการขยายตัวของ Postamble postamble มีการประมวลผลซ้ำ: มันมีคำนำของและเดินทอดน่องของ,
นี้มีการขยายไปยังรายการ{1..3}
,1 ,2 ,3
ทั้งสองรายการa b c
และ,1 ,2 ,3
a,1 a,2 a,3 b,1 b,2 b,3 c,1 c,2 c,3
จะรวมกันแล้วในรูปแบบรายการสินค้า
มันอาจช่วยให้คำอธิบายเกี่ยวกับพีชคณิตแบบ psuedo - เกี่ยวกับวิธีการแยกวิเคราะห์นิพจน์เหล่านี้โดยที่วงเล็บ "[]" หมายถึงอาร์เรย์, "+" หมายถึงการเรียงลำดับของอาร์เรย์ที่เรียงกัน
นี่คือวิธีที่นิพจน์แรกถูกขยาย (หนึ่งขั้นต่อบรรทัด):
{{a..c},{1..3}}
{a..c} + {1..3}
[a b c] + [1 2 3]
a b c 1 2 3
และนี่คือวิธีที่นิพจน์ที่สองถูกขยาย:
{a..c},{1..3}
{a..c} * ,{1..3}
[a b c] * [,1 ,2 ,3]
a,1 a,2 a,3 b,1 b,2 b,3 c,1 c,2 c,3