Score:0

ข้อผิดพลาดทางไวยากรณ์ขณะใช้ End of Message (EOM) ภายในลูป while ในสคริปต์เชลล์อูบุนตู

ธง in

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

โปรดช่วยฉันแก้ไขปัญหานี้

บรรทัดที่เกิดข้อผิดพลาด:

อุณหภูมิ = "คิว"
gmx_mpi make_ndx -f pull_sim.gro -o index.ndx <<EOM
อุณหภูมิ $
อีโอเอ็ม

ข้อผิดพลาด:

./Run_Pull_Code.sh: 105: ข้อผิดพลาดทางไวยากรณ์: จุดสิ้นสุดของไฟล์ที่ไม่คาดคิด (คาดว่า "เสร็จสิ้น")

กรุณาค้นหารหัสต่อไปนี้แบบเต็ม (อ้างอิงถึงบรรทัดที่ 80 ถึง 83 ที่นี่):

#!/bin/sh
# ความคิดเห็นด้านบนตั้งค่าไฟล์ sh ให้ดำเนินการเป็นล่าม (ทีละบรรทัด)

# การค้นหาไดเร็กทอรีการทำงานปัจจุบัน
BASEDIR=$(pwd)
echo "ขณะนี้ฉันอยู่ในไดเร็กทอรีต่อไปนี้:"
เสียงสะท้อน "$BASEDIR"
เสียงสะท้อน " "


#################################################### ########################################
# การตั้งค่าตำแหน่งรหัสการดึงและการลดลง (ทั้งหมดใน nm)
#################################################### ########################################
DECREMENT=0.5 #ขั้นตอนในหน่วยนาโนเมตร
RANGE=1 #จากตำแหน่งสูงสุดไปยังตำแหน่งต่ำสุด
MID_POS=9.327 #สังเกตโมเลกุลน้ำ (O อะตอม) สูงสุดของผิวน้ำ
INIT_POS=$( echo "$MID_POS + $RANGE" | bc -l) # ตำแหน่งเริ่มต้น
LAST_POS=$( echo "$MID_POS - $RANGE" | bc -l) # ตำแหน่งสุดท้าย
CURR_POS=$INIT_POS # การกำหนดตำแหน่งเริ่มต้นเป็นตำแหน่งปัจจุบัน


LOOP_CNT=0
ในขณะที่ [ 1 -eq "$(echo "${LAST_POS} <= ${CURR_POS}" | bc)" ]
ทำ 
    #เพิ่มมูลค่า
    LOOP_CNT=$( echo "$LOOP_CNT + 1" | bc -l)
    DISTANCE=$CURR_POS

    # การตั้งค่าหมายเลขลูป (X) เป็นหมายเลขรหัสดึงสำหรับการจำลอง (X)
    SIM_CNT=$LOOP_CNT

    # การสร้างไดเร็กทอรี (1) X_Pull (2) X_Pull/Making
    DIR_NAME_MAIN=$SIM_CNT"_Pull"
    mkdir $DIR_NAME_MAIN
    DIR_NAME_MAKING=$SIM_CNT"_ดึง/สร้าง"
    mkdir $DIR_NAME_MAKING
    
    เสียงสะท้อน " "
    echo "ฉันสร้างไดเร็กทอรีแล้ว"
    เสียงสะท้อน " "

    # การคัดลอกไฟล์จากโฟลเดอร์ข้อกำหนดเบื้องต้นไปยังโฟลเดอร์ที่สร้างขึ้นใหม่
    cp ข้อกำหนดเบื้องต้น/Avo_decanol.pdb ข้อกำหนดเบื้องต้น/water_box.pdb $DIR_NAME_MAKING
    cp ข้อกำหนดเบื้องต้น/simulation_file.mdp ข้อกำหนดเบื้องต้น/topol.top $DIR_NAME_MAIN
    
    #################################################### ########################################
    # การสร้างกล่องจำลอง "pull_sim.gro"
    #################################################### ########################################
    ซีดี $DIR_NAME_MAKING
    #(1) กำหนดระยะห่างของ decanol จากผิวน้ำ และสร้างกล่อง decanol เพียงกล่องเดียวที่มีขนาดเท่ากับกล่องน้ำ
    ระยะทาง=9.5 
    gmx_mpi editconf -f Avo_decanol.pdb -o Dec_box.pdb -center 2.5 2.5 $DISTANCE -box 5 5 12
    #(2) การสร้างไฟล์ cat ส่วนหัวและส่วนท้ายคงที่ในรูปแบบ PDB
    # 4 บรรทัดแรกของไฟล์ PDB ใดๆ จะมีข้อมูลของขนาดกล่องและชื่อ ฯลฯ
    # เพียงคัดลอกสี่บรรทัดลงในไฟล์ HEADER PDB แยกต่างหากโดยใช้คำสั่งต่อไปนี้
    sed -n '1,4p' Dec_box.pdb > HEADER.pdb
    # 2 บรรทัดสุดท้ายก็เหมือนกันกับไฟล์ PDB ทั้งหมด ดังนั้นให้คัดลอกบรรทัดเหล่านี้ไปยังไฟล์ ENDER PDB โดยใช้คำสั่งต่อไปนี้
    sed -n '38,39p' Dec_box.pdb > ENDER.pdb
    #(3) แยกคุณสมบัติ decanol atom ออกจากไฟล์ PDB (บรรทัดที่ 5 ถึง 37) โดยใช้คำสั่งต่อไปนี้
    sed -n '5,37p' Dec_box.pdb > file_1.pdb
    #(4) แยกคุณสมบัติอะตอมของน้ำออกจากไฟล์ PDB (บรรทัดที่ 5 ถึง 15004) โดยใช้คำสั่งต่อไปนี้
    sed -n '5,15004p' water_box.pdb > file_2.pdb
    #(5) ตอนนี้เชื่อมต่อไฟล์ทั้งหมดข้างต้นกับไฟล์ PDB ผิวน้ำตามลำดับต่อไปนี้:
    cat HEADER.pdb file_1.pdb file_2.pdb ENDER.pdb > pull_sim.pdb
    #(6) จัดเรียงจำนวนอะตอมทั้งหมดใน pull_sim.pdb และแปลงเป็นไฟล์ GRO, ไฟล์ pull_sim.gro
    gmx_mpi editconf -f pull_sim.pdb -o pull_sim.gro -center 2.5 2.5 6.0 -box 5.0 5.0 12.0 -resnr 1

    # คัดลอกไฟล์ pull_sim.gro ที่เพิ่งสร้างจากการสร้างโฟลเดอร์ไปยังโฟลเดอร์ก่อนหน้า
    ซีดี ../
    การสร้าง cp/pull_sim.gro ./
        
    เสียงสะท้อน " "
    echo "สร้าง pull box แล้ว"
    เสียงสะท้อน " "
    
    #################################################### ########################################
    #เริ่มจำลอง
    #################################################### ########################################
    # (1) การสร้างไฟล์ดัชนี
    อุณหภูมิ = "คิว"
    gmx_mpi make_ndx -f pull_sim.gro -o index.ndx <<EOM
    อุณหภูมิ $
    อีโอเอ็ม
    # (2) การสร้างไฟล์ tpr จากโมดูล grompp
    gmx_mpi grompp -f simulation_file.mdp -p topol.top -c pull_sim.gro -n index.ndx -maxwarn 0 -o nvt.tpr
    #เคลียร์เนื้อหาทั้งหมด
    แจ่มใส
    เสียงสะท้อน " "
    echo "#####################************ การจำลองการดึง: $LOOP_CNT *********** #####################"
    เสียงสะท้อน " "
    # (3) mdrun
    gmx_mpi mdrun -v -deffnm nvt -nb gpu -pme gpu -pmeft gpu -ผูก gpu
        
    # ย้ายกลับไปที่โฟลเดอร์หลัก
    ซีดี ../
    
    # ลดระยะทางสำหรับลูปถัดไป
    CURR_POS=$( echo "$CURR_POS - $DECREMENT" | bc -l)
เสร็จแล้ว
    
#แจ่มใส
เสียงสะท้อน " "
เสียงสะท้อน "เสร็จสมบูรณ์"
เสียงสะท้อน " "
terdon avatar
cn flag
ข้อผิดพลาดคืออะไร? และคำสั่ง `gmx_mpi make_ndx` นี้คาดหวังอินพุตใด คุณจะเรียกใช้ได้อย่างไรหากคุณไม่ได้ใช้ heredocs (EOM) คุณจะส่งไฟล์หรือไม่? สตริง?
terdon avatar
cn flag
และความคิดเห็นทั่วไปบางประการ: i) หลีกเลี่ยงการใช้ตัวพิมพ์ใหญ่สำหรับชื่อตัวแปรในเชลล์สคริปต์ ตามแบบแผน ตัวแปรสภาพแวดล้อมส่วนกลางจะถูกทำให้เป็นตัวพิมพ์ใหญ่ ดังนั้นการมีตัวแปรของคุณเองเป็นตัวพิมพ์ใหญ่อาจทำให้ชื่อตัวแปรเกิดการชนกัน ซึ่งแก้ไขจุดบกพร่องได้ยากมาก แนวทางปฏิบัติที่ดีโดยทั่วไปคือการหลีกเลี่ยงการใช้ตัวพิมพ์ใหญ่ในเชลล์สคริปต์ ii) ***อ้างตัวแปรของคุณสองครั้งเสมอ*** ดู[ความหมายด้านความปลอดภัยของการลืมอ้างตัวแปรในเชลล์ bash/POSIX](https://unix.stackexchange.com/q/171346) iii) คุณสามารถเพิ่มตัวแปรโดยกำเนิดในเชลล์ โดยไม่จำเป็นต้องมี `bc`: `let LOOP_CNT++` หรือ `((LOOP_CNT++))`
in flag
ขอบคุณสำหรับคำแนะนำ. ตอนนี้ฉันได้แก้ไขและกล่าวถึงข้อผิดพลาดแล้ว โปรดดู
Score:2
ธง cn

Heredocs ไม่สามารถเยื้องได้เหมือนสคริปต์ที่เหลือ (เว้นแต่คุณจะใช้ -EOM แต่คุณสามารถเยื้องด้วยแท็บเท่านั้น) ท้ายที่สุดแล้ว จุดประสงค์ของเอกสารนี้คือการอนุญาตให้คุณเขียนสิ่งที่จะปรากฏขึ้น อย่างที่เป็น. ซึ่งหมายความว่า อีโอเอ็ม ไม่สามารถเป็นเช่นนี้:

ในขณะที่บางสิ่งบางอย่าง; 
ทำ
    คำสั่ง <<EOM
    สวัสดี!
    อีโอเอ็ม
เสร็จแล้ว  

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

ในขณะที่บางสิ่งบางอย่าง; 
ทำ
    คำสั่ง <<EOM
    สวัสดี!
อีโอเอ็ม
เสร็จแล้ว  

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

ค=0;
ในขณะที่ [ $c -eq 0 ]; 
ทำ
    แมว <<EOM
    สวัสดี!
อีโอเอ็ม
    ให้ c ++
เสร็จแล้ว  

จะพิมพ์:

$fo.sh
    สวัสดี!

ขณะนี้:

ค=0;
ในขณะที่ [ $c -eq 0 ]; 
ทำ
    แมว <<EOM
สวัสดี!
อีโอเอ็ม
    ให้ c ++
เสร็จแล้ว  

จะพิมพ์:

$fo.sh
สวัสดี!

สุดท้าย เมื่อรันสคริปต์ของคุณ ฉันได้รับข้อผิดพลาดอื่น:

$fo.sh
ขณะนี้ฉันอยู่ในไดเร็กทอรีต่อไปนี้:
/บ้าน/terdon/foo
 
/home/terdon/scripts/foo.sh: บรรทัดที่ 108: คำเตือน: เอกสารที่นี่ที่บรรทัดที่ 84 คั่นด้วยจุดสิ้นสุดของไฟล์ (ต้องการ `EOM')
/home/terdon/scripts/foo.sh: บรรทัดที่ 109: ข้อผิดพลาดทางไวยากรณ์: จุดสิ้นสุดของไฟล์ที่ไม่คาดคิด

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

muru avatar
us flag
Heredocs สามารถย่อหน้าได้ เมื่อคุณใช้ยัติภังค์นำหน้าคำที่ใช้คั่น (เช่น `
terdon avatar
cn flag
@muru จริง ฉันไม่เคยจำเรื่องนั้น ฉันแค่ไม่เยื้องพวกเขาและปล่อยไว้อย่างนั้น แต่จุดที่ดีขอบคุณ
in flag
ขอบคุณมากครับท่าน ตอนนี้ปัญหาของฉันได้รับการแก้ไขแล้ว

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา