Назад | Перейти на главную страницу

Как мне прочитать несколько строк из STDIN в переменной?

Я искал этот вопрос безрезультатно. Я автоматизирую процесс сборки здесь, на работе, и все, что я пытаюсь сделать, это получить номера версий и крошечное описание сборки, которое может быть многострочным. Система, на которой он работает, - OSX 10.6.8.

Я видел все, от использования CAT до обработки каждой строки по мере необходимости. Я не могу понять, что мне использовать и почему.

Попытки

read -d '' versionNotes

Приводит к искаженному вводу, если пользователю приходится использовать клавишу Backspace. Также нет хорошего способа завершить ввод, поскольку ^ D не завершается, а ^ C просто завершает процесс.

read -d 'END' versionNotes

Работает ... но все еще искажает ввод, если требуется клавиша возврата.

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

Неправильно завершает ввод (потому что я слишком поздно искать совпадение с пустой строкой).

man bash упоминает «…

Подстановку команды $ (cat file) можно заменить на эквивалентную, но более быструю $ (<file).

… »

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

и я согласен, что об этом стоит упомянуть - echo "$myVar" отобразил бы ввод в том виде, в каком он был задан.

Попробуй это:

пользователь @ хост: ~ $ read -d '' x <<EOF
> mic
> check
> one
> two
> EOF

Без разрывы строк:

пользователь @ хост: ~ $ echo $x
mic check one two

С участием разрывы строк:

пользователь @ хост: ~ $ echo "$x"
mic
check
one
two

Обратитесь к отличному Руководство по Bash для всех ваших потребностей в сценариях bash.

В частности, Bash FAQ содержит это под номером 1:

Как я могу прочитать файл (поток данных, переменную) построчно (и / или поле за полем)?

Я решил эту проблему, работая с каждой строкой, пока не получил пустую строку. Это работает достаточно хорошо для моей ситуации. Но если кто-то хочет добавить лучшее решение, смело делайте это.

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

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

Вы можете запустить редактор вроде vim, pico ...

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

Сначала несколько исправлений:

  1. Чтобы разрешить «редактирование» на линии, используйте -e который использует строку чтения (так что у вас есть история bash и все функции редактирования)
  2. -d требуется только один персонаж. Например. from 'END' принимает 'E', и всякий раз, когда пользователь пишет 'E', чтение останавливается (я думаю, это не то, что вы хотите ...)

Есть несколько возможностей сделать это. Я бы пошел на чтение построчно и остановился, когда была найдена пустая строка (хотя вы можете установить любое стоп-слово):

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

У вас есть несколько методов.

Один из самых простых способов:

MYVAR=$(yourcommand)
echo $"MYVAR"

Например:

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

Мы используем конструкцию с использованием xargs и ctrl-d для взлома. Я не совсем удовлетворен этим, но он, безусловно, выполняет свою работу по принятию многострочного пользовательского ввода и вставке его в переменную (форматирование без изменений). (Первое и третье присвоения добавляют кавычки к содержимому входных данных xargs.)

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

Мы используем ReminderBody как тело электронного письма, отправляемого по почте (через bash).

Видеть: http://tldp.org/LDP/abs/html/internal.html#READR

Использовать read и обратите внимание, что если вы закончите строку с \ новая строка игнорируется. Итак, вы могли:

#!/bin/bash

read -p "version: " version
echo $version

# enter some input and end long lines with "\", then plain enter at the end
read -p "description: " description
echo -e "$version\n$description >> yourfile.txt