คุณจะเรียกใช้คำสั่งในวิธีทุบตีจนสำเร็จ


237

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

echo "Please change password"
while passwd
do
echo "Try again"
done

ฉันลองวนรอบหลายครั้งแล้ว:

while `passwd`
while [[ "`passwd`" -gt 0 ]]
while [ `passwd` -ne 0 ]]
# ... And much more

แต่ฉันไม่สามารถทำให้มันใช้งานได้

คำตอบ:


403
until passwd
do
  echo "Try again"
done

หรือ

while ! passwd
do
  echo "Try again"
done

20
ยากที่จะกด Ctrl-C จากนี้
DonGar

หากคุณคิดว่าคุณจะต้องยกเลิกสิ่งนี้ให้เปิดอินสแตนซ์ใหม่ของเชลล์ของคุณ (ตัวอย่างพิมพ์ "bash") และเมื่อคุณต้องการยกเลิกให้ไปที่หน้าต่างเทอร์มินัลอื่นและฆ่า bash ที่เพิ่งเกิดใหม่ กระบวนการ.
อีธาน

50
ง่ายต่อการ Ctr-C จากสิ่งนี้: until passwd; do echo "Try again"; sleep 2; done- สิ่งที่คุณต้องทำคือกด Ctr-C ทันทีหลังจาก (ภายในสองวินาทีที่กำหนด) สิ่งที่echoทำได้
คริสเตียน

9
@azmeuk: บางสิ่งบางอย่างเช่นลองuntil passwd || (( count++ >= 5 )); do echo "foo"; done(ทุบตีเพียงให้แน่ใจว่าจะนับตั้งค่าเป็น 0 ถ้า varaible ที่มีอยู่) ถ้าคุณต้องการนี้ได้ดวลจุดโทษธรรมดาเพิ่มเคาน์เตอร์ในร่างกายและใช้ []
จัสตินเซน

2
หลังจากอ้างถึงหน้านี้หลายครั้งฉันตัดสินใจที่จะสร้างฟังก์ชั่นทุบตีทั่วไปเพื่อลองคำสั่งอีกครั้งนี่คือ: gist.github.com/felipou/6fbec22c4e04d3adfae5
felipou

94

คุณต้องทดสอบ$?แทนซึ่งเป็นสถานะการออกของคำสั่งก่อนหน้า passwdออกด้วย 0 หากทุกอย่างทำงานได้ดีและไม่ใช่ศูนย์หากการเปลี่ยน passwd ล้มเหลว (รหัสผ่านไม่ถูกต้องรหัสผ่านไม่ตรงกัน ฯลฯ ... )

passwd
while [ $? -ne 0 ]; do
    passwd
done

ด้วยเวอร์ชัน backtick ของคุณคุณกำลังเปรียบเทียบเอาต์พุตของ passwd ซึ่งจะเป็นสิ่งที่ชอบEnter passwordและไม่confirm passwordชอบ


2
ไม่ควรจะเป็นอย่างนั้น$??
Shawn Chin

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

เมื่อความสำเร็จถูกระบุโดยรหัสทางออกที่ไม่เป็นศูนย์นี่คือสิ่งที่คุณต้องการ
Gudlaugur Egilsson

2
ผมคิดว่านี่จะดีขึ้นเล็กน้อยโดยการเปลี่ยนแปลงครั้งแรกpasswdกับ/bin/falseถ้าคุณมีคำสั่งที่ยาวและซับซ้อนบางอย่างที่คุณไม่ต้องการที่จะให้สองรุ่น
coladict

ควรเป็นคำตอบที่ยอมรับได้ สิ่งนี้ควรใช้กับเชลล์ส่วนใหญ่ (ทดสอบใน bash, mksh และ ash) และสามารถปรับให้เข้ากับสถานการณ์ได้ง่าย
linuxandria

73

เพื่ออธิบายรายละเอียดเกี่ยวกับคำตอบของ @Marc B

$ passwd
$ while [ $? -ne 0 ]; do !!; done

เป็นวิธีที่ดีในการทำสิ่งเดียวกันที่ไม่ใช่คำสั่งเฉพาะ


11
ไม่ทำงานสำหรับฉันโชคไม่ดี (ฉันไม่พบคำสั่ง '!!') มันควรจะทำงานอย่างไร
Johannes Rudolph

2
มันเป็นเคล็ดลับทุบตีเพื่อเรียกใช้คำสั่งก่อนหน้า ตัวอย่างเช่นหากคุณลืมที่จะเขียนsudoต่อหน้าคำสั่งคุณสามารถทำได้sudo !!เพื่อเรียกใช้คำสั่งก่อนหน้าด้วยสิทธิ์พิเศษของรูท
JohnEye

1
ฉันสามารถสร้างสคริปต์ในโปรไฟล์ของฉันที่สามารถทำได้ดังนั้นฉันสามารถไป: $ makelastwork
230910

2
วิธีการนอนหลับระหว่างวิ่ง?
Kamil Dziedzic

6

คุณสามารถใช้การวนซ้ำไม่สิ้นสุดเพื่อทำสิ่งนี้:

while true
do
  read -p "Enter password" passwd
  case "$passwd" in
    <some good condition> ) break;;
  esac
done

2
นี่เป็นคำตอบเดียวที่ไม่ต้องใช้คำสั่งหลายบรรทัดในฟังก์ชั่น ฉันทำ&& breakหลังจากคำสั่งการตรวจสอบของฉันแม้ว่าจะเป็นกรณีที่เลือก
carlin.scott

4

หากทุกคนที่ต้องการลองใหม่ จำกัด :

max_retry=5
counter=0
until $command
do
   sleep 1
   [[ counter -eq $max_retry ]] && echo "Failed!" && exit 1
   echo "Trying again. Try #$counter"
   ((counter++))
done

1
until $(command)โดยทั่วไปผิดเสมอ ใช้until commandแทน $(...)เป็นสาเหตุที่ทำให้การส่งออกของcommandที่จะเป็นตัวเองทำงานเป็นคำสั่งและออกจากสถานะของคำสั่งรองที่จะเป็นสิ่งที่ห่วงตัดสินใจที่จะเรียกใช้หรือล้มเหลวใน; เป็นเพียงถ้ามีเป็น stdout ที่ออกจากสถานะของคำสั่งตัวเองถือว่าไม่เมื่อแทนคำสั่งเป็นปัจจุบัน
ชาร์ลส์ดัฟฟี่

$commandไม่ใช่ตัวยึดตำแหน่งที่ยอดเยี่ยม - ดูBashFAQ # 50ว่าทำไมการใช้สตริงเพื่อจัดเก็บคำสั่งไม่น่าเชื่อถือโดยกำเนิด ถึงกระนั้นมันก็ยังดีกว่าเดิม ถอนการโหวตลง
ชาร์ลส์ดัฟฟี่

3
while [ -n $(passwd) ]; do
        echo "Try again";
done;

3
นี่ไม่ใช่วิธีที่จะทำ ... คุณกำลังคัดค้าน stdout ของ psswd แล้วทำการทดสอบแบบ unary @duckworthd เป็นสิ่งที่ดี
Ray Foss

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