Вопрос или проблема
Я безуспешно искал ответ на этот вопрос в Google. Я автоматизирую процесс сборки на работе, и все, что я пытаюсь сделать, это получить номера версий и небольшое описание сборки, которое может быть многострочным. Система, на которой это работает, это 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
Не заканчивает ввод должным образом (потому что я слишком поздно ищу соответствие с пустой строкой).
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"
отобразила бы ввод так, как он был дан.
Попробуйте это:
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
Обратитесь к отличному Bash Guide для всех ваших нужд в bash-сценариях.
В частности, Bash FAQ содержит этот номер под номером #1:
Как читать файл (поток данных, переменную) построчно (и/или по полям)?
Вы можете запустить редактор, такой как vim, pico…
${VISUAL:-${EDITOR:-vi}} source/application.yml
Я решил эту проблему, обрабатывая каждую строку, пока не получил пустую строку. Это достаточно хорошо работает для моей ситуации. Но если кто-то хочет добавить более лучшее решение, пожалуйста, сделайте это.
echo "---
notes: |" > 'version.yml'
while read line
do
# прервать, если строка пуста
[ -z "$line" ] && break
echo " $line" >> "source/application.yml"
done
~ $ txt=; while read line; do [[ $line == '.' ]] && break; txt+="$line\n"; done; txt=${txt:0:-2}
Hi! This should work, right?
Cheers!
.
~ $ echo $txt
Hi! This should work, right?
Cheers!
~ $
Это должно работать в zsh! 😃
txt=${txt:0:-2} – Чтобы удалить последний перевод строки.
P.S. Я думаю, эта функция прочитает многострочный ввод в переменную, названную как $1, переданную этой функции.
# например, 'readlines blaat' установит для $blaat многострочный ввод.
readlines() {
eval "unset $1"
while read line
do
[[ $line == '.' ]] && break
eval "$1+='$line\n'"
done
eval "$1=\${$1:0:-2}"
}
Сначала несколько исправлений:
- Чтобы разрешить “редактирование” строки, используйте
-e
, который использует readline (так у вас будет история bash и все функции редактирования) -d
принимает только один символ. Например, из ‘END’ берет ‘E’, и всякий раз, когда пользователь вводит ‘E’, чтение останавливается (думаю, это не то, что вам нужно…)
Есть несколько возможностей сделать это. Я бы предпочел читать построчно и останавливать, когда найдена пустая строка (хотя вы могли бы установить любое стоп-слово):
unset tmp
while :
do
read line
[[ $line == "" ]] && tmp="${tmp:0:$((${#tmp}-1))}" && break
tmp="$tmp"$line$'\n'
done
Мы используем конструкцию с использованием xargs и ctrl-d для завершения. Я не полностью доволен этим, но он, безусловно, выполняет задачу по приему многострочного ввода от пользователя и вводу в переменную (с сохранением форматирования). (Первое и третье присваивания добавляют кавычки вокруг содержимого ввода xargs.)
printf '%s\n' "When finished hit ctrl-d on a new line to proceed. " "" ""
# это загрузит ввод пользователя в переменную вместо файла
reminderBody="\""
reminderBody+=$( xargs -0 )
reminderBody+="\""
Мы используем reminderBody как тело электронной почты, отправляемой через mail (via bash).
Как говорится в вашем комментарии, ввод идет от пользователя через терминал: Вы можете использовать read
для чтения многострочного ввода через
read -d $'\04' versionNotes
который устанавливает разделитель на EOF, который в Unicode является 0x04
, так что вы можете читать ввод до тех пор, пока не будет дан CTRL-D
.
У вас есть несколько методов.
Один из самых простых методов:
MYVAR=$(yourcommand)
echo $"MYVAR"
Например:
MYVAR=$(ls /)
echo $"MYVAR"
Смотрите: http://tldp.org/LDP/abs/html/internal.html#READR
Используйте read
и обратите внимание, что если вы закончите строку с \
, то новая строка игнорируется. Так что вы можете сделать:
#!/bin/bash read -p "version: " version echo $version # введите некоторый ввод и завершите длинные строки с "\", затем просто нажмите Enter в конце read -p "description: " description echo -e "$version\n$description >> yourfile.txt
.
Ответ или решение
Чтение ввода из стандарта (STDIN) в переменную является одной из распространенных задач, с которой может столкнуться специалист по IT при автоматизации различных процессов, таких как сборка программного обеспечения. Проблема заключается в том, что пользовательский ввод может содержать несколько строк, и необходимо корректно их обработать и сохранить в переменную для последующего использования. Давайте рассмотрим несколько подходов к решению этой задачи, применимых в условиях операционной системы OSX 10.6.8.
Теория
Когда мы говорим о вводе данных из STDIN, важно помнить, что стандартный ввод — это поток ввода, который по умолчанию считывает данные из терминала. Один из базовых инструментов для работы с вводом в сценариях оболочки (shell) – это команда read
. Однако команду read
нужно уметь правильно применять, чтобы она могла обрабатывать многострочный ввод.
Важным моментом является определение маркера завершения ввода пользователем. В UNIX-подобных системах, таким маркером часто выступает комбинация клавиш Ctrl+D
, которая посылает End Of Transmission (EOT), сигнализируя об окончании ввода.
Пример
На основе вашего описания, вы сталкиваетесь с проблемой получения чистого, не искаженного ввода, который пользователь может редактировать с помощью клавиши Backspace. Приведу пример решения на основе использования цикла while
с командой read
:
#!/bin/bash
echo "Введите описание версии (завершите ввод, введя пустую строку):"
versionNotes=""
while IFS= read -r line; do
# Прерываем ввод, если строка пуста
[ -z "$line" ] && break
# Добавляем новую строку к переменной
versionNotes+="$line"$'\n'
done
# Удаляем последнюю новую строку для корректного оформления результата
versionNotes="${versionNotes%$'\n'}"
echo "Ваш ввод:"
echo "$versionNotes"
Применение
В этом подходе:
-
Команда
read
: Используется с флагом-r
, который подавляет интерпретацию обратного слеша как экранирующего символа. Это полезно, если пользователь вводит символы, которые потенциально могут быть интерпретированы иначе. -
Цикл
while
: Продолжается до тех пор, пока пользователь не введет пустую строку, что используется как сигнал окончания ввода. -
Конкатенация строк: Используем встроенный символ
$'\n'
для добавления новой строки к переменнойversionNotes
. -
Результат: В конце убираем последнюю добавленную новую строку, что позволяет избежать лишнего пустого строкового символа в выводе.
Этот механизм позволяет пользователю вводить многострочный текст с возможностью редактирования, а также определяет окончание ввода через ввод пустой строки. Таким образом, данный скрипт эффективно решает вашу задачу, обеспечивая корректное сохранение данных.
Дополнительные рекомендации
-
Документация: Регулярное обращение к документации и справочным ресурсам может существенно облегчить процесс написания скриптов. Например, изучение руководств по Bash, таких как Bash Guide, расширит ваше понимание шелл-скриптинга.
-
Редакторы: Используйте возможности современных текстовых редакторов для редактирования
source/application.yml
. Как было упомянуто, запуск редактора через переменные среды${VISUAL:-${EDITOR:-vi}}
может обеспечить более управляемый процесс редактирования. -
Ввод-вывод: Всегда тестируйте скрипты на небольших примерах, прежде чем внедрять их в рабочие процессы. Это поможет избежать ошибок и упрощает отладку кода.
Итак, предложенный подход позволяет гибко работать с пользовательским многострочным вводом в сценариях автоматизации под ОС OSX. Надеюсь, это решение поможет оптимизировать ваш рабочий процесс сборки.