ZSH: คำสั่งอ่านล้มเหลวภายในฟังก์ชันทุบตี“ อ่าน: 1: -p: ไม่มีตัวประมวลผลร่วม”


29

แก้ไข:

bashดูเหมือนว่าการทำงานภายใน zshแต่ดูเหมือนว่ามันมีปัญหาที่เกี่ยวข้องกับ หากมีเว็บไซต์ที่ดีกว่าในการโพสต์ปัญหานี้ให้ฉันทราบ


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

read.sh

#!/bin/bash
test() {
  read -p "Here be dragons. Continue?" -n 1 -r
  if [[ $REPLY =~ ^[Yy]$ ]]
  then
    echo "You asked for it..."
  fi
}

รหัสจากนี้โพสต์ SO

จัดหาไฟล์และ / หรือผลในข้อผิดพลาดต่อไปนี้:test read:1: -p: no coprocessเอาท์พุทเดียวกันเมื่อฉันวางไว้ในของฉัน.bashrc

แก้ไข ::

@hennes

  1. ฉันต้องการให้ฟังก์ชั่นอยู่ในไฟล์ config ดังนั้นฉันสามารถเรียกมันได้จากไดเรกทอรีใด ๆ (โดยเฉพาะอย่างยิ่ง. bashrc หรือ. zshrc ของฉัน)
  2. ฉันแก้ไขการจัดรูปแบบของบรรทัดที่คอมเม้นต์แรกแล้ว ปัญหายังคงมีอยู่zsh
  3. เวอร์ชั่น Bash คือ 3.2 แต่คุณได้ช่วยฉันหาปัญหาแล้วว่าเป็นปัญหากับ zsh ไม่ใช่การทุบตี

1) มีสถานที่ใด ๆ ที่คุณโทรจริงฟังก์ชั่นการทดสอบ () ? 2) #! /bin/bashมีช่องว่างด้านหลังเธอ shebang? ฉันคิดว่าสิ่งเหล่านั้นไม่ได้รับอนุญาต? 3) '#! / usr / bin / env bash' น่าจะดีกว่า 4) เวอร์ชั่นทุบตีใด? (ฉันทดสอบกับทุบตี 4.1.10 ใน FreeBSD และไม่มีข้อผิดพลาด)
Hennes

ฉันติดแท็กคำถามอย่างไม่เหมาะสมฉันกำลังใช้อยู่zshแต่ไม่คิดว่าจะมีข้อขัดแย้งกับสคริปต์ทุบตี ฉัน retagged มันและตอบคำถามของคุณ ขอบคุณที่ชี้นำฉันในทิศทางที่ถูกต้อง!
Nick Tomlin

คุณจะเริ่มโปรแกรมได้อย่างไร shebang (#!) interpreter` ./read.shสายเป็นสิ่งจำเป็นเท่านั้นถ้าคุณต้องการที่จะเรียกใช้ไฟล์ที่มี ไม่จำเป็นว่าคุณจะเรียกใช้ด้วยวิธีอื่นใดหรือถ้าคุณใส่ไว้ในสคริปต์เริ่มต้น และถ้าคุณต้องการเรียกใช้เป็น zsh ด้วย `zsh ./read.sh 'ดังนั้นบรรทัดที่ขึ้นต้นด้วย # จะถูกละเว้น พวกเขายังสับสนตั้งแต่พวกเขาให้ความประทับใจที่คุณใช้ bash เมื่อคุณใช้ zsh)
Hennes

@NickTomlin คุณรู้วิธีที่จะทำให้มันทำงานโดยไม่ต้องใส่ Enter after 'y' (ใต้ ZSH) หรือไม่?
syntagma

@REACHUS อนิจจาฉันทำไม่ได้ โชคดี!
Nick Tomlin

คำตอบ:


49

–pตัวเลือกไม่ได้หมายความว่าสิ่งเดียวกันกับbash's readในตัวคำสั่งและzsh' s readในตัวคำสั่ง ในzsh's readคำสั่ง–pวิธีการ - เดา -‘การป้อนข้อมูลจะถูกอ่านจาก coprocess ได้.’ผมขอแนะนำให้คุณแสดงพร้อมท์ของคุณด้วยหรือechoprintf

นอกจากนี้คุณยังอาจต้องเปลี่ยน–n 1ด้วยหรือ–k–k 1


zshเทียบเท่าbash's read -p promptมี

read "?Here be dragons. Continue?"

สิ่งใดหลังจาก a ?ในอาร์กิวเมนต์แรกจะถูกใช้เป็นสายอักขระพรอมต์

และแน่นอนคุณสามารถระบุชื่อตัวแปรที่จะอ่าน (และนี่อาจเป็นรูปแบบที่ดีกว่า):

read "brave?Here be dragons. Continue?"
if [[ "$brave" =~ ^[Yy]$ ]]
then
    ...
fi

(โดยทั่วไปการอ้างอิงตัวแปรของเชลล์เป็นความคิดที่ดีเช่นกัน)


ขอขอบคุณสำหรับคำอธิบายว่าทำไมสิ่งนี้จึงไม่ทำงานอย่างถูกต้อง ฉันจะตรวจสอบความแตกต่างเช่นนี้ในอนาคต
Nick Tomlin

คำอธิบายที่ดีขอบคุณ! มีปัญหาเดียวกันที่แน่นอน
iosifv

8

รหัสนี้ดูเหมือนจะทำสิ่งที่คุณต้องการใน zsh
(โปรดทราบว่าคำถามที่คุณอ้างถึงระบุอย่างชัดเจนว่ามีไว้สำหรับการทุบตี)

#! / usr / bin / env zsh

ทดสอบ()
{
  echo -n "นี่คือมังกรดำเนินการต่อหรือไม่"
  อ่านซ้ำ

  ถ้า [[$ REPLY = ~ ^ [Yy] $]]
  แล้วก็
    echo "คุณถามหา ... "
  Fi
}

ทดสอบ

สามความคิดเห็น:


ขอขอบคุณสำหรับความช่วยเหลือของคุณ. ฉันได้รับคำตอบให้กับ @scott เนื่องจากคำอธิบายว่าทำไมสิ่งนี้ถึงไม่ทำงาน แต่ตัวอย่างข้อมูลที่คุณให้มาทำงานได้อย่างสมบูรณ์แบบ
Nick Tomlin

1
อีกสามสิ่ง: นี่อาจเป็นคำถามที่ดีที่สุดใน SO (เพราะเป็นคำถามการเขียนโปรแกรม) 2) เชลล์บางตัวไม่สามารถใช้งานร่วมกันได้ (man zsh ส่งคืนเนื้อหาที่แตกต่างกันสำหรับ read -p แล้ว man bash ทำ 3) วิธีแก้ไขอื่นคือการค้นหา vared -c -p 'prompt prompt'
Hennes

+1 ขอบคุณที่แจ้งให้เราทราบ ฉันจะนำคำถามการเขียนโปรแกรมเป็นศูนย์กลางในอนาคตไปที่ SO
Nick Tomlin

ในบรรทัดสุดท้ายของฟังก์ชั่นนี้คุณควรเพิ่มREPLY=""เพื่อล้างตัวแปร REPLY มิฉะนั้นถ้าคุณ echo $ REPLY คุณจะเห็นว่ามันยังคงถูกตั้งค่าไว้จนกว่าคุณจะเปิดหรือปิดเทอร์มินัลหรือตั้งค่าอีกครั้ง
jasonleonhard

0

รุ่นนี้ช่วยให้คุณมีมากกว่าหนึ่งกรณีyหรือY, nหรือN

  1. ทางเลือก: ทำซ้ำคำถามจนกว่าจะมีคำถามอนุมัติ

  2. ทางเลือก: ละเว้นคำตอบอื่น ๆ

  3. ทางเลือก: ออกจากเทอร์มินัลหากคุณต้องการ

    confirm() {
        echo -n "Continue? y or n? "
        read REPLY
        case $REPLY in
        [Yy]) echo 'yup y' ;; # you can change what you do here for instance
        [Nn]) echo 'nope n' ;;
        # Here are a few optional options to choose between
        # Any other answer:
    
        # 1. Repeat the question
        *) confirm ;;
    
        # 2. ignore
        # *) ;;
    
        # 3. Exit terminal
        # *) exit ;;
    
        esac
        # REPLY=''
    }

สังเกตสิ่งนี้ด้วย: ในบรรทัดสุดท้ายของฟังก์ชันนี้ให้ล้างตัวแปร REPLY มิฉะนั้นถ้าคุณecho $REPLYจะเห็นมันยังคงตั้งค่าไว้จนกว่าคุณจะเปิดหรือปิดเครื่องหรือตั้งค่าอีกครั้ง

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