ฉันจะอ่านหลายบรรทัดจาก STDIN ลงในตัวแปรได้อย่างไร


24

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

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

ความพยายามในการ

read -d '' versionNotes

ผลลัพธ์เป็นอินพุตที่อ่านไม่ออกถ้าผู้ใช้ต้องใช้คีย์ backspace นอกจากนี้ยังไม่มีวิธีที่ดีในการยุติอินพุตเนื่องจาก ^ D ไม่ได้ยุติและ ^ C เพิ่งออกจากกระบวนการ

read -d 'END' versionNotes

ใช้งานได้ ... แต่ยังอ่านไม่ออกถ้าจำเป็นต้องใช้ปุ่ม Backspace

while read versionNotes
do
  echo "  $versionNotes" >> "source/application.yml"
done

ไม่สิ้นสุดอินพุตอย่างถูกต้อง (เพราะฉันสายเกินไปที่จะค้นหาการจับคู่กับสตริงว่าง)


คุณได้รับข้อมูลนี้จากผู้ใช้ถูกต้องหรือไม่
เกล็นแจ็คแมน

แก้ไข; ฉันต้องการให้ผู้ใช้ป้อนข้อมูลนี้ใน terminal เมื่อรันสคริปต์
Robert K

1
คุณยังไม่ได้ทำให้ชัดเจนฉันอยากจะพูด
poige

คำตอบ:


20

man bash กล่าวถึง« ...

การแทนที่คำสั่ง $ (ไฟล์ cat) สามารถแทนที่ได้ด้วยการเทียบเท่า แต่เร็วกว่า $ (ไฟล์ <)

... »

$ myVar=$(</dev/stdin)
hello
this is test
$ echo $myVar
hello this is test
$ echo "$myVar"
hello
this is test

และฉันก็เห็นด้วยว่านี่เป็นสิ่งที่ควรค่าแก่การกล่าวขวัญ - echo "$myVar"จะแสดงอินพุตตามที่ได้รับ


1
วิธีหยุดหลังจากป้อนหลายบรรทัด? ถ้าฉันกด Ctrl C มันจะหยุด แต่ตัวแปรไม่ถูกบันทึก!
Nikhil

2
เทอร์มินัลUNIX®มี "วินัย": en.wikipedia.org/wiki/Line_discipline •ตรวจสอบว่า "eof" หมายถึงอะไร•อ่านอ่านman sttyค้นหาวิธีรับการตั้งค่าปัจจุบัน
บทกวี

2
ctrl-d เพื่อหยุด
freb

9

ลองสิ่งนี้:

user@host:~$ read -d '' x <<EOF
> mic
> check
> one
> two
> EOF

ไม่มีการแบ่งบรรทัด:

user@host:~$ echo $x
mic check one two

ด้วยตัวแบ่งบรรทัด:

user@host:~$ echo "$x"
mic
check
one
two

2
-d ''เป็นสิ่งที่ฉันต้องการ ขอบคุณ
Bruno Bronosky

@Bruno ความสุขของฉัน; มันเป็นเรื่องยุ่งยาก โดยเฉพาะอย่างยิ่งในครั้งแรกที่ดูมาตรฐานค่อนข้าง มีประโยชน์ทีเดียวแม้ว่าเมื่อคุณได้รับความยุ่งเหยิงต่างๆ
เสียง

8

อ้างอิงถึงBash Guide ที่ยอดเยี่ยมสำหรับทุกความต้องการของสคริปต์ bash

โดยเฉพาะอย่างยิ่งคำถามที่พบบ่อย Bash นี้มีที่หมายเลข # 1:

ฉันจะอ่านไฟล์ (data stream, variable) ทีละบรรทัด (และ / หรือ field-by-field) ได้อย่างไร?


คุณบอกว่าจะใช้read -rแต่ฉันจะให้มันทำเช่นนั้นจาก STDIN ได้อย่างไร? ฉันพยายามใช้read -rแต่เนิ่นๆ
Robert K

มันอ่านจาก stdin โดยค่าเริ่มต้น
adaptr

2

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

echo "---
notes: |" > 'version.yml'

while read line
do
  # break if the line is empty
  [ -z "$line" ] && break
  echo "  $line" >> "source/application.yml"
done

ใช้read -rแทน
adaptr

2

คุณสามารถเริ่มแก้ไขเช่นเสียงเรียกเข้า, pico ...

${VISUAL:-${EDITOR:-vi}} source/application.yml

อืม ... นั่นตอบคำถามของ OP ได้อย่างไร?
adaptr

เขาสามารถเริ่มแก้ไขจากสคริปต์
Mircea Vutcovici

และนั่นก็ทำให้สำเร็จ เขาต้องการใช้ข้อความจากไฟล์ในสคริปต์ไม่ใช่เขียนข้อมูลลงในไฟล์
adaptr

เขาไม่ต้องการอ่านข้อความจากผู้ใช้และเขียนลงในไฟล์ โปรดอ่านความคิดเห็นที่เพิ่มเข้าไปในคำถาม
Mircea Vutcovici

1

แก้ไขครั้งแรกไม่กี่:

  1. เพื่ออนุญาตให้ "รุ่น" ในการใช้บรรทัด-eที่ใช้ readline (เพื่อให้คุณมีประวัติทุบตีและคุณสมบัติการแก้ไขทั้งหมด)
  2. -dใช้เวลาเพียงหนึ่งตัวละคร เช่นจาก 'END' จะใช้ 'E' และเมื่อใดก็ตามที่ผู้ใช้เขียน 'E' การอ่านจะหยุด (ฉันเดาว่านั่นไม่ใช่สิ่งที่คุณต้องการ ... )

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

unset tmp
while :
do 
 read line
 [[ $line == "" ]] && tmp="${tmp:0:$((${#tmp}-1))}" && break
 tmp="$tmp"$line$'\n'
done

0

คุณมีหลายวิธี

หนึ่งในวิธีที่ง่ายที่สุดคือ:

MYVAR=$(yourcommand)
echo $"MYVAR"

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

MYVAR=$(ls /)
echo $"MYVAR"

ยกเว้นว่าฉันไม่ได้ดำเนินการคำสั่งเชลล์เช่น LS ฉันขออินพุตหลายบรรทัดจากผู้ใช้
Robert K

นี่เป็นการฝึกฝนที่แย่มาก ห้ามประมวลผลเอาต์พุตของls!
adaptr

@adaptr เราเคยได้ยินมาก่อนคุณจะแนะนำทางเลือกที่ดีได้ไหม
เสียง

0

เรากำลังใช้โครงสร้างโดยใช้ xargs และ ctrl-d สำหรับการทำลาย ฉันไม่พอใจกับมันอย่างสมบูรณ์ แต่แน่นอนว่ามันจะทำหน้าที่รับอินพุตผู้ใช้หลายสายและบรรจุลงในตัวแปร (การฟอร์แมตเหมือนเดิม) (การมอบหมายแรกและที่สามเพิ่มเครื่องหมายคำพูดล้อมรอบเนื้อหาของอินพุต xargs)

    printf "\\033[1mWhen finished hit ctrl-d on a new line to proceed.\\033[0m  \\n\\n" 
    # this will load the user's input into a variable instead of a file 
    reminderBody="\"" 
    reminderBody+=$( xargs -0 ) 
    reminderBody+="\"" 

เราใช้ alertBody เป็นหัวเรื่องของอีเมลที่ส่งทางไปรษณีย์ (ผ่าน bash)


-1

ดู: http://tldp.org/LDP/abs/html/internal.html#READR

ใช้readและโปรดทราบว่าหากคุณวางสายด้วย\บรรทัดใหม่จะถูกละเว้น ดังนั้นคุณสามารถทำได้:

#! / bin / ทุบตี

read -p "version:" version
echo $ version

# ป้อนอินพุตและสิ้นสุดบรรทัดยาวด้วย "\" จากนั้นป้อนธรรมดาที่ท้าย
อ่าน -p "คำอธิบาย:" คำอธิบาย
echo -e "$ version \ n $ description >> yourfile.txt

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

ABS เป็นความน่าประหลาดใจในสัดส่วนที่น่ากลัว 90% ของมันผิดปกติ
adaptr

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