“ แปรปรวน” เครื่องหมายและ (พื้นหลังกระบวนการ)


9

ฉันต้องการทราบว่ามีวิธีที่จะใส่เครื่องหมายและในตัวแปรและยังใช้เพื่อส่งกระบวนการไปยังพื้นหลัง

งานนี้:

BCKGRND=yes
if [ "$BCKGRND" = "yes" ]; then
    sleep 5 &
else
    sleep 5
fi

แต่มันจะไม่เจ๋งมั้ยที่จะบรรลุห้าสายเหล่านั้นด้วยเพียงอันเดียว? ชอบมาก

BCKGRND='&'
sleep 5 ${BCKGRND}

แต่นั่นไม่ได้ผล หาก BCKGRND ไม่ได้ตั้งค่าให้ใช้งานได้ แต่เมื่อตั้งค่ามันจะตีความว่าเป็นตัวอักษร '&' และข้อผิดพลาด


หลังจากใช้เครื่องหมายแอมecho $!
เปอร์

คำตอบ:


9

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

อีกตัวเลือกหนึ่งคือการตัดการโทรในฟังก์ชัน:

mayberunbg() {
  if [ "$BCKGRND" = "yes" ]; then
    "$@" &
  else
    "$@"
  fi
}

... จากนั้นตั้งค่าตัวแปรตามต้องการ:

$ BCKGRND=yes mayberunbg sleep 3
[1] 14137
$
[1]+  Done                    "$@"
# or
$ BCKGRND=yes
$ mayberunbg sleep 3
[1] 14203
$
[1]+  Done                    "$@"
$ BCKGRND=no mayberunbg sleep 3
# 3 seconds later
$

อะไรไม่ed? +1 ต่อไปนี่เป็นคำตอบที่สะอาดที่สุด
สตีเฟ่น Kitt

LOL @StephenKitt; ตอนนี้เกียร์กำลังเปลี่ยน
Jeff Schaller

ฉันชอบคำตอบ eval สำหรับความเรียบง่าย แต่คำสั่งในโลกแห่งความเป็นจริงของฉันที่ฉันต้องการให้พื้นหลังนั้นซับซ้อนเกินไปกับตัวแปรมากเกินไปที่จะใช้งานได้สบาย @ jeff-schaller ให้คำตอบที่ชี้ให้ฉันไปในทิศทางที่ฉันไป แต่แทนที่จะใช้ฟังก์ชั่นฉันใส่คำสั่งทั้งหมดลงในตัวแปรจากนั้นใช้คำสั่ง if style เพื่อเรียกใช้งานคำสั่งโดยมีหรือไม่มี &
BrowncoatOkie

11

คุณสามารถพลิกสิ่งต่าง ๆ และแปรปรวน“ เบื้องหน้า”:

FOREGROUND=fg
sleep 5 & ${FOREGROUND}

ตั้งค่าFOREGROUNDเป็นtrueหรือว่างเปล่าเพื่อเรียกใช้กระบวนการในพื้นหลัง (การตั้งค่าFOREGROUNDให้trueทำงานในพื้นหลังเป็นที่ยอมรับกันอย่างสับสน! ชื่อตัวแปรที่เหมาะสมถูกปล่อยไว้เป็นแบบฝึกหัดสำหรับผู้อ่าน)


4
มันดี แต่มันจะไม่ทำงานในเชลล์ที่ไม่มีการควบคุมงาน (เช่นสคริปต์ใด ๆ ยกเว้นว่าset -mใช้แล้ว)
mosvy

9

คุณอาจต้องใช้eval:

eval "sleep 5" "$BCKGRND"

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


2
คำตอบที่มีevalควรมีคำเตือนว่าควรจัดการอย่างระมัดระวัง ดูเช่นคำตอบนี้
Ralf

ฉันไม่เข้าใจปัญหาที่เกิดขึ้นจาก"$BCKGRND"การหาข้อโต้แย้งที่ว่างเปล่า
mosvy

2
@Ralf ไม่เกี่ยวข้องอย่างแน่นอนในกรณีนี้ ไม่มีอะไรพิเศษเกี่ยวกับ eval - คุณสามารถรันคำสั่งผ่านการขยายเลขคณิตตัวอย่างเช่น อาจจะมีคำเตือนดังกล่าวต่อต้านการใช้ทุบตี (หรือเปลือกที่คล้ายกัน) เลย ;-) #
38211

1
@Kusalananda evalจะเข้าร่วมการโต้เถียงกับช่องว่างก่อนที่จะทำการ eval จริง ลองดูสิeval printf "'{%s}\n'" foo "" "" "". eval foo "" "" "" ""คล้ายกันอย่างสมบูรณ์eval fooไม่ว่าจะเป็นอะไรIFSหรืออะไรก็ตาม
mosvy

1
คำสั่งที่ถูก eval'ed ควรจะอยู่ในราคาคู่ถ้ามันมีอักขระพิเศษใด ๆ eval 'sleep $TIMEOUT' "$BACKGROUND"เช่น มิฉะนั้นคุณอาจได้รับการขยายสองเท่าหากตัวแปรขยายไปยังตัวแปรอื่นหรือมีอักขระพิเศษ นอกจากนี้ข้อความที่ซ้อนกันอาจทำให้เกิดความยุ่งยากได้
Barmar
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.