เมื่อใดที่ {a, b, c} ถูกขยายเป็น bash เมื่อใด


13

สคริปต์ทุบตีที่มี

for i in {a,b}-{1,2}; do
  echo $i;
done

พิมพ์

a-1
a-2
b-1
b-2

เมื่อดำเนินการ นี่คือสิ่งที่ฉันคาดไว้ - ขณะที่การ{a,b}ก่อสร้างขยายออกไป

อย่างไรก็ตามเมื่อสคริปต์ (อื่น) มี

v={a,b}-{1,2}
echo $v

มันพิมพ์

{a,b}-{1,2}

ซึ่งไม่ใช่สิ่งที่ฉันคาดหวัง a-1 a-2 b-1 b-2ผมคาดว่ามันจะพิมพ์ เห็นได้ชัดว่าการ{a,b}สร้างไม่ได้ขยาย

ฉันสามารถทำให้มันขยายได้อย่างนั้น

v=$(echo {a,b}-{1,2})

จากข้อสังเกตเหล่านี้ฉันมีสองคำถาม: 1) {a,b}โครงสร้างจะขยายเมื่อไหร่? 2) เป็น$(echo {a,b}-{1,2})วิธีที่ต้องการเพื่อกระตุ้นการขยายเมื่อต้องการหรือไม่


1
=นี้เป็นอย่างน้อยให้สอดคล้องกับความจริงที่ว่าคุณจะไม่สามารถทำให้ตัวแปรอาร์เรย์ด้วยง่าย ตัวอย่างเช่นv=a-1 a-2จะไม่ทำงาน
grochmal

@grochmal - นั่นเป็นเพราะคุณกำลังกำหนดค่าสเกลาร์ v=a-1 a-2วิธีการกำหนดอาร์เรย์ให้กับตัวแปร assign 'a-1' to variable v and run 'a-2' v=(a-1 a-2) ต่อท้ายมัน vv+=(b-1 b-2)
cas

คำตอบ:


15

คู่มือทุบตีกล่าวว่า:

SIMPLE COMMAND EXPANSION
When a simple command is executed, the shell performs the following
expansions, assignments, and redirections, from left to right.
[...]
4. The  text  after the = in each variable assignment undergoes tilde
   expansion, parameter expansion, command substitution, arithmetic
   expansion, and quote removal before being assigned to the variable.

v={a,b}-{1,2}การขยายตัวรั้งไม่ได้อยู่ในรายชื่อดังกล่าวจึงไม่ได้ดำเนินการสำหรับการมอบหมาย ตามที่ระบุไว้โดย @Wildcard การขยายที่เรียบง่ายที่v=a-1 v=b-1 ...จะไม่มีความรู้สึกอยู่ดี

นอกจากนี้เมื่อเรียกใช้งานecho $vสิ่งต่อไปนี้จะนำไปใช้:

EXPANSION
Expansion is performed on the command line after it has been split
into words. [...]

The order of expansions is: brace expansion; tilde expansion, 
parameter and variable expansion, arithmetic expansion, and command
substitution (done in a left-to-right fashion); word splitting; and
pathname expansion.

การขยายของ Brace เกิดขึ้นก่อนการขยายตัวตัวแปรดังนั้นการจัดฟันที่มอบหมายให้$vไม่ขยาย

แต่คุณสามารถทำสิ่งนี้:

$ var_this=foo var_that=bar
$ echo $var_{this,that}
foo bar

การขยายด้วย$(echo ...)ควรจะทำงานหากคุณไม่มีช่องว่างใด ๆ ในสตริงที่จะขยายและด้วยเหตุนี้จะไม่เกิดปัญหากับการแยกคำ วิธีที่ดีกว่าอาจใช้ตัวแปรอาเรย์ถ้าคุณทำได้

เช่นบันทึกการขยายตัวลงในอาร์เรย์และเรียกใช้คำสั่งบางอย่างที่มีค่าขยาย:

$ v=( {a,b}-{1,2} )
$ some_command "${v[@]}"

5

จุดที่น่าสนใจ อาจมีประโยชน์เป็นข้อความที่ตัดตอนมาจากman bash:

ตัวแปรอาจได้รับมอบหมายให้ตามคำสั่งของรูปแบบ

      name = [ value ]

ถ้าค่าไม่ได้รับตัวแปรที่ได้รับมอบหมายสตริงโมฆะ ค่าทั้งหมดได้รับการขยายตัวของตัวหนอนพารามิเตอร์และการขยายตัวตัวแปรการทดแทนคำสั่งการขยายตัวทางคณิตศาสตร์และการลบเครื่องหมายคำพูด (ดูการขยายด้านล่าง)

โปรดทราบว่าการขยายรั้งไม่ได้กล่าวถึงในรายการ

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


1
บางทีนี่อาจ? "2. คำที่ไม่ใช่การกำหนดตัวแปรหรือการเปลี่ยนเส้นทางจะถูกขยาย (ดูการขยายเชลล์)"
Jeff Schaller

@JeffSchaller คุณถูกต้อง ที่จริงแล้วคำถามนี้ตอบได้ดีที่สุดโดยเพียงแค่อ่านส่วน "คำสั่งขยายง่าย" ( LESS=+/SIMPLE man bash)
Wildcard

0

ตามความรู้ของ lil '{a, b, c} จะถูกขยายออกเมื่อมันถูกสะท้อนหรือใช้โดยตรงกับคำสั่งเช่น: mkdir ~ / {a, b, c}, แต่เมื่อมันถูกตั้งค่าเป็นตัวแปรมันควรจะถูกประเมินก่อน echoing หรือใช้เป็น arggument!

u@h:~$ echo {a,b}-{1,2}
a-1 a-2 b-1 b-2
u@h:~$ v={a,b}-{1,2}
u@h:~$ echo $v
{a,b}-{1,2}
u@h:~$ eval echo $v
a-1 a-2 b-1 b-2

เนื่องจากคุณมี "a" ตามด้วย "b" ตามลำดับอัลฟา [az] และ "1" ตามด้วย "2" ในคำสั่งธันวาคม [0-9]: คุณสามารถใช้เครื่องหมายจุดคู่ได้ ".. " insteed of comma ", "

u@h:~$ echo {a..b}-{1..2}
a-1 a-2 b-1 b-2
u@h:~$ v={a..b}-{1..2}
u@h:~$ echo $v
{a..b}-{1..2}
u@h:~$ eval echo $v
a-1 a-2 b-1 b-2

1
คำถามคือทำไมvไม่ได้ตั้งค่าเป็นตัวอักษร "a-1 a-2 b-1 b-2" หรืออย่างน้อยก็ไม่มีข้อผิดพลาดเกิดขึ้นเมื่อคุณพิมพ์คำสั่ง: v=a-1 v=a-2 v=b-1 v=b-2(ซึ่งคุณคาดว่าจะได้รับมอบหมายให้ขยายตัวแปร) มันเป็นคำถามที่ดี สิ่งนี้ไม่ได้ตอบคำถามจริงๆ
Wildcard

@SatoKatsura "การขยายตัวของตัวแทน" ควรจะหมายถึงอะไร? มีการขยายพารามิเตอร์การขยายชื่อพา ธ และการขยายรั้ง - ซึ่งคุณสามารถอ้างถึงและสิ่งที่แตกต่างกันทั้งหมด หรือคุณหมายถึงการแยกคำ?
Wildcard

0

การกำหนดให้กับตัวแปรใน bash ไม่ได้ขยายการแสดงออก

สำหรับสคริปต์เล็ก ๆ นี้ x จะมี"*"และไม่ขยาย"*":

#!/bin/bash
x=*
echo "$x"

อย่างไรก็ตามค่าบางค่าจะถูกขยายอ้างอิง คำตอบที่ดีจาก ilkkachu

นิพจน์จะถูกขยายเมื่อถูกประเมิน

แบบนี้:

x=$(echo *)        # <-- evaluation of "*"
echo "$x"

หรือเช่นนี้

x=*
echo $x            # <-- evaluation of $x

หรือเช่นนี้

x=*
eval echo "$x"     # <-- evaluation of `echo *`

การทริกเกอร์$()เป็นเรื่องธรรมดาและฉันคิดว่ามันเป็นที่นิยมมากกว่าevalแต่สิ่งที่ดีที่สุดอาจไม่ทำให้เกิดการประเมินเลยจนกว่าตัวแปรจะถูกใช้จริงในคำสั่ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.