ฉันจะส่งตัวอักษรไปยังคำสั่งราวกับว่าพวกเขามาจากไฟล์ได้อย่างไร


22

ฉันจะส่งตัวอักษรไปยังคำสั่งราวกับว่าพวกเขามาจากไฟล์ได้อย่างไร

ตัวอย่างเช่นฉันพยายาม:

wc < "apple pear orange"
-bash: apple pear orange: No such file or directory

คำตอบ:



18

อีกสองวิธี (ซึ่งอนุญาตให้ใช้อินพุตแบบหลายบรรทัดโดยไม่มีความพยายามพิเศษ):

  1. ใช้ "เอกสารที่นี่":

    $ wc << EOF
    ลูกแพร์แอปเปิ้ลส้ม
    EOF
      1 3 18
    $

    EOFสตริงเป็นตัวคั่น คุณสามารถใช้สตริงใดก็ได้ EOFเป็นเพียงทางเลือกทั่วไป

  2. ใช้ tty เป็นอินพุต:

    $ wc
    ลูกแพร์แอปเปิ้ลส้ม
    Ctrl+D
      1 3 18
    $

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

    $ grep v
    สุนัขจิ้งจอกสีน้ำตาลด่วน              (พิมพ์) 
    กระโดดข้าม                       (พิมพ์) 
    กระโดดข้าม                       (นี่คือผลลัพธ์จาก grep!) 
    สุนัขขี้เกียจ                   (พิมพ์)
    Ctrl + D
                                    (ไม่มีผลลัพธ์ที่นี่) 
    $

สำหรับเร็กคอร์ด: <<<ฟอร์มยังอนุญาตให้อินพุตแบบหลายบรรทัดโดยไม่ต้องใช้ความพยายามเป็นพิเศษเนื่องจาก"สตริง -enclosed สามารถมีการขึ้นบรรทัดใหม่ แน่นอน<< EOFรูปแบบ (ไวยากรณ์ here-doc ดั้งเดิม) อ่านได้ง่ายกว่าถ้าคุณมีอินพุตหลายบรรทัด
alexis

หน้าคนบอกว่าที่นี่สตริงไวยากรณ์คือ<<< word- แน่นอนในบริบทของเปลือก, a wordสามารถเป็นสตริงที่ยกมามีช่องว่างและขึ้นบรรทัดใหม่! D'โอ้! เห็นได้ชัดว่ามันไปโดยไม่บอก (และอันที่จริงแล้วฉันไม่เห็นมันพูดถึงใน man page เลย) :-( ขอบคุณที่บอกให้ฉันทราบ!
G-Man พูดว่า 'Reinstate Monica'

ฉันจะไม่เรียกมันว่าเรียบง่ายหรือชัดเจนจริงๆ A wordถูกกำหนดใน manpage เป็น "ลำดับของอักขระที่ถือว่าเป็นหน่วยเดียวโดยเชลล์" (aka "token") และคุณจำเป็นต้องรู้ว่าสตริงที่ยกมานั้นจะถือว่าเป็น "a single unit" ในแง่ที่เกี่ยวข้อง (หลังจาก ทับขวาประมวลผลการขยายตัวตัวแปรอื่น ๆ" แต่แน่นอนว่าเป็นวัตถุประสงค์ทั้งสองครั้ง quoting ในเปลือก (ราคาเดียวยังป้องกันจากการขยาย.) รูปแบบการประมวลผลของเปลือกเป็นความคิดที่ดีมากออกและอะไร แต่ง่าย..
อเล็กซิส

@alexis: เมื่อฉันไปด้านบนเช่นนั้นและใส่อิโมติคอนพวกเราควรพิจารณาถึงความเป็นไปได้ที่ฉันจะแดกดัน
G-Man กล่าวว่า 'Reinstate Monica'

10

<()แม้ว่าจะมีการแก้ปัญหาที่ถูกต้องที่นี่หลายไวยากรณ์อื่นที่สามารถเป็นบางครั้งที่มีประโยชน์คือการใช้คำสั่งใน สิ่งนี้จะอนุญาตให้คุณสร้างวัตถุ file-descriptor มากกว่า 1 อันในบรรทัดคำสั่ง

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

ตัวอย่างเช่นการเปรียบเทียบไฟล์โฮสต์บนสองโหนดโดยไม่ต้องคัดลอกไฟล์โฮสต์ไปยัง localhost:

diff -Naur <(cat /etc/hosts) <(ssh -q otherhost 'cat /etc/hosts')

การ<เปลี่ยนเส้นทางไฟล์ไปยัง STDIN และ()สร้าง subshell เพื่อเรียกใช้คำสั่งระหว่างวงเล็บ มันคือ STDOUT จาก subshell ที่ส่งผ่านไปยัง STDIN ของคำสั่งที่กำลังรัน

มันเป็นวิธีที่ง่ายกว่าในการสร้างไฟล์ "input" มากกว่าหนึ่งคำสั่งแทนที่จะพยายามใช้หลาย ๆ เอกสารที่นี่หรือพยายาม echo หลายคำสั่งไปยังไพพ์ไลน์


<fileorpathnameเปลี่ยนเส้นทาง stdin แต่<(subcmd)ไม่; มันทดแทนชื่อที่เมื่อ / ถ้าเปิดโดยโปรแกรมสามารถอ่าน stdout จาก subcmd < <(subcmd)(พื้นที่ที่จำเป็น) ไม่ stdin subcmd |เปลี่ยนเส้นทางจากไฟล์ที่เกือบจะเหมือน คุณdiffสามารถอ่านหนึ่งในอินพุตของมันจาก stdin โดยการระบุอาร์กิวเมนต์ของ-แต่ไม่ใช่ทั้งคู่
dave_thompson_085

นั่นคือการทดแทนกระบวนการซึ่งไม่ได้รับการสนับสนุนซึ่งแตกต่างจากชิ้นส่วนที่คุณอ้างว่าทำออกมา
phk

1
ความแตกต่างของฉันทำงานได้ดีในทุบตีบน Ubuntu 16.04 และระบบ Solaris 11.2 ที่ฉันต้องทดสอบด้วย เป็นไปได้ว่าอาจไม่ทำงานกับเชลล์ทั้งหมดในระบบปฏิบัติการทั้งหมด อันที่จริงแล้วการสร้างตัวอธิบายไฟล์ที่สามารถใช้อ่านเอาต์พุตจากกระบวนการย่อยราวกับว่ากำลังอ่านไฟล์ เนื่องจาก diff รับสองอาร์กิวเมนต์ไฟล์จึงสามารถอ่านเอาต์พุตของกระบวนการย่อยทั้งสองผ่านตัวอธิบายไฟล์ที่สร้างขึ้นและเปรียบเทียบได้
ทิมเคนเนดี

คุณอาจต้องการที่จะเพิ่มคำตอบของคุณแตกต่างระหว่างและcmd <(cmd2 ...) cmd < <(cmd2 ...)อดีตอนุญาตให้ใช้ข้อมูลที่ได้รับมา (เอาต์พุตของ cmd2) เพื่อใช้แทนชื่อไฟล์ cmd2 ... | cmdหลังเป็นเทียบเท่ากับ คำสั่งต้องถูกเขียนเพื่อยอมรับอินพุต stdin อย่างชัดเจนและหลายคำสั่งไม่ใช่ นี่เป็นความจริงโดยเฉพาะอย่างยิ่งของเชลล์สคริปต์
DocSalvager

8

คุณสามารถใช้ท่อ

echo "apple pear orange" | wc

8
ไพพ์ไม่เหมือนกับ "การอ่านจากไฟล์" ตัวอย่างเช่นคุณไม่สามารถค้นหาย้อนหลังในไพพ์ได้ในขณะที่คุณสามารถทำได้ในไฟล์
rbialon

0

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

#!/usr/bin/expect
spawn telnet localhost 8555
expect "Escape character is '^]'."
send "Hello World\n"
expect "Connection closed by foreign host."
sleep 1
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.