คำสั่ง Bash ในสตริงกำลังทำงานเมื่อฉันสร้างสตริงไม่ใช่เมื่อฉันใช้ในภายหลัง


10

ฉันค่อนข้างใหม่เปลือกสคริปต์ แต่ได้เกือบเสร็จสมบูรณ์สคริปต์ซึ่งทำให้การใช้เป็นโปรแกรม lftp ส่วนของสคริปต์ที่ฉันมีปัญหาคือเมื่อฉันสร้างคำสั่งยาว ๆ (คั่นด้วย;)

for var in something
do
    ...
    commands_to_run+="echo Result is `tail -n 1 $somefile`;"
done

สิ่งที่ฉันสังเกตเห็นคือtailโปรแกรมที่ห่อใน backticks กำลังถูกเรียกใช้เมื่อ for for วนซ้ำ แต่ไม่ใช่เมื่อฉันเรียกใช้ชุดคำสั่งในสคริปต์ของฉัน

น่าเสียดายที่เนื้อหาของ $ somefile ยังไม่พร้อมสำหรับการตรวจสอบ ฉันจะรับคำสั่งให้ดำเนินการเมื่อฉันต้องการมันได้หรือไม่ในขณะที่ฉันกำลังสร้างสตริง?

คำตอบ:


8

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

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

มันง่ายกว่ามากที่จะดูตัวอย่างดังนั้นลองใช้อันนี้ซึ่งจะนำคุณไปสู่เส้นทางที่ถูกต้อง:

for((i=0;i<10;i++)); do 
  date +%s.%N  # Print a timestamp (in format seconds.nanoseconds)
  test="echo \$(date +%s.%N)" # Save a command to do the same
  sleep 1      # Sleep for a second
  eval "$test" # Evaluate the command saved in variable 'test'
  echo         # Print a new line before the next iteration
done

นี่คือตัวอย่างผลลัพธ์จากตัวอย่างด้านบน (ตัดเป็นหนึ่งซ้ำ):

1398832186.133661344
1398832187.139076728

คุณจะสังเกตเห็นว่าการประทับเวลาครั้งที่สองสำหรับแต่ละวงวนนั้นประมาณหนึ่งวินาทีหลังจากครั้งแรก ในทางกลับกันถ้าคุณทำการทดสอบเดียวกันโดยไม่ต้องหลบเลี่ยง$ในtestคำจำกัดความและการลบการevalประทับเวลาทั้งสองจะใกล้เคียงกัน

อย่าใช้นิสัยevalในสถานการณ์ส่วนใหญ่ แต่นี่เป็นหนึ่งในสิ่งที่ฉันไม่รู้วิธีหลีกเลี่ยงมัน หวังว่านี่จะช่วยได้ โชคดี!


ขอบคุณมากฉันลองใช้$(...)ตามที่แนะนำ Hauke ​​แต่แบ็กสแลชเป็นกุญแจสำคัญ
Ricky

ดีใจที่ได้ช่วย - โปรดจำไว้ว่ากุญแจที่นี่เป็นevalเพราะคุณสามารถทำสิ่งเดียวกันได้โดยไม่ต้องหลบหนี$และใช้เครื่องหมายคำพูดเดี่ยว ( ') แทนที่จะเป็นเครื่องหมายคำพูดคู่ ( ") เพื่อล้อมรอบคำสั่งของคุณ
daBeamer

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

คำสั่งใดที่คุณพยายามเรียกใช้งาน ฉันอยู่ภายใต้การแสดงผลที่คุณต้องการในechoสตริงที่มีเนื้อหารวมถึงผลลัพธ์ของคำสั่งซ้อนการดำเนินการล่าช้า
daBeamer

1
@Ricky ฉันจะต้องเห็นด้วยกับทุกจุดจาก @HaukeLaging รหัสที่เป็นลบechoจะไม่ทำงานเพราะไม่มีคำสั่งevalแต่เป็นสตริง หากคุณมีตัวอย่างที่เกี่ยวข้องกับเรามากขึ้นเราสามารถช่วยคุณได้
daBeamer

6

การอ้างอิงมีหลายระดับ คำพูดคู่ ( "...") ช่องว่างการป้องกันและตัวอักษรพิเศษหลาย ( ~, &, |, ;, ... ) แต่ไม่ได้ป้องกันการขยายตัวพารามิเตอร์และแทนคำสั่ง

คุณต้องใช้เครื่องหมายอัญประกาศเดี่ยว ( ') หรือแบ็กสแลชข้างหน้าอักขระ "อันตราย"

โดยทั่วไป: คุณควรพิจารณาใช้$(tail ...)แทน backticks Backticks เป็นมาตรฐานเก่า แต่เรากำลังพูดถึงเก่าที่$()ไม่ก่อให้เกิดปัญหาสำหรับคนส่วนใหญ่ เวอร์ชันใหม่อ่านง่ายกว่าและซ้อนกันได้ นับประสาปัญหาการจัดรูปแบบที่นี่ใน sx ...


ขอบคุณสำหรับการตอบกลับอย่างรวดเร็ว Hauke น่าเสียดายที่การแทนที่ backticks ด้วยที่แนะนำ$(...)ยังคงให้ผลลัพธ์เหมือนกัน - เชลล์เรียกใช้งานนี้เมื่อสตริงของฉันถูกกำหนด
Ricky

@ Ricky นั่นไม่ใช่คำแนะนำทางเลือก คุณจะใช้$()แต่คุณต้องการคำพูดเดียวต่อไป
Hauke ​​Laging

ดังนั้นไม่มีการรวมกันของตัวละครเหล่านั้นจะบรรลุสิ่งที่ฉันหลังจาก
Ricky

@Ricky ยากที่จะเข้าใจเกี่ยวกับ "คุณต้องการคำพูดอย่างใดอย่างหนึ่ง" คืออะไร? เห็นได้ชัดว่าคุณไม่ได้ลองเลย
Hauke ​​Laging

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