STDINから複数の行を変数に読み込むにはどうすればよいですか?


24

私はこの質問を無駄に使い続けてきました。私は職場でビルドプロセスを自動化しています。私がやろうとしているのは、バージョン番号と、複数行のビルドの小さな説明を取得することだけです。これが実行されるシステムはOSX 10.6.8です。

CATの使用から、必要に応じて各行を処理するまでのすべてを見てきました。何を使うべきなのか、なぜだかわからない

試み

read -d '' versionNotes

ユーザーがバックスペースキーを使用する必要がある場合、入力が文字化けします。また、^ Dは終了せず、^ Cはプロセスを終了するだけなので、入力を終了する良い方法はありません。

read -d 'END' versionNotes

動作しますが、バックスペースキーが必要な場合は入力が文字化けします。

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

入力を適切に終了しません(空の文字列との一致を検索するには遅すぎるため)。


ユーザーからこの情報を取得していますか?
グレンジャックマン

正しい; スクリプトを実行するときに、ユーザーにこの情報を端末に入力してほしい。
ロバートK

1
あなたは自分自身を明確にしていない、私はむしろ言いたい。
poige

回答:


20

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"ます。与えられたとおりに入力を表示していたでしょう。


1
複数行入力後に停止する方法は?Ctrl Cを押すと停止しますが、変数は保存されません!
ニキル

2
UNIX®端子は「規律」を持っている:en.wikipedia.org/wiki/Line_disciplineは •DOは読み•「EOF」どういう意味それをチェックアウトman stty、現在の設定を取得する方法を見つける、
poige

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 ''まさに必要なものです。ありがとう
ブルーノ・ブロノスキー

@ブルーノ私の喜び; トリッキーなものです。特に一見すると、かなり標準的に見えます。ただし、さまざまな特異性を理解したら、非常に便利です。

8

すべてのbashスクリプトのニーズについては、優れたBashガイドを参照してください。

特に、Bash FAQにはこれが番号1に含まれています。

ファイル(データストリーム、変数)を行ごと(および/またはフィールドごと)に読み取るにはどうすればよいですか?


を使用すると言いますread -rが、どうすればSTDINから取得できますか?私はread -r早くから使用しようとしました。
ロバートK

デフォルトで標準入力から読み取ります。
アダプター

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代わりに使用してください。
アダプター

2

vim、picoなどのエディターを起動できます...

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

ええと...それはOPの質問にどのように答えますか?
アダプター

スクリプトからエディターを開始できます。
ミルチャVutcovici

そして、それは正確に何を達成しますか?彼はテキストを使用したいから、スクリプトでファイルでない書き込み情報ファイルを。
アダプター

彼は、ユーザーからテキストを読み取ってファイルに書き込むことはしませんでした。質問に追加されたコメントを読んでください。
ミルチャVutcovici

1

最初にいくつかの修正:

  1. -ereadlineを使用する行で「編集」を許可するには(bash履歴とすべての編集機能が必要です)
  2. -d1文字のみを取ります。たとえば、「END」から「E」を取得し、ユーザーが「E」を書き込むと、読み取りが停止します(これはあなたが望んでいることではないと思います...)

これを行うにはいくつかの可能性があります。行ごとに読み取りに行き、空の行が見つかったら停止します(ただし、ストップワードを設定できます)。

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

0

いくつかの方法があります。

最も簡単な方法の1つは次のとおりです。

MYVAR=$(yourcommand)
echo $"MYVAR"

例えば:

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

LSのようなシェルコマンドを実行していないことを除いて。ユーザーに複数行の入力を要求しています。
ロバートK

これは非常に悪い習慣です。ls!の出力を処理しません
アダプター

@adaptr聞いたことはありますが、良い代替案を提案してください。

0

破壊にはxargsとctrl-dを使用する構成を使用しています。私はそれで完全に満足しているわけではありませんが、確かに複数行のユーザー入力を取り込んで変数に詰め込むという仕事をしています(そのままのフォーマット)。(最初と3番目の割り当てでは、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+="\"" 

reminderBodyは、メール(bash経由)で送信される電子メールの件名として使用します。


-1

参照:http : //tldp.org/LDP/abs/html/internal.html#READR

使用readして、あなたが終了した場合に沿っことに注意してください\改行は無視されます。だからあなたができる:

#!/ bin / bash

read -p "version:"バージョン
エコー$ version

#入力を入力し、「\」で長い行を終了し、最後に単純な入力
read -p "description:"説明
echo -e "$ version \ n $ description >> yourfile.txt

改行を無視した段落だけが必要な場合は、はい。しかし、これはビルドスクリプトのリリースノートの生成されたリストであるため、これらの改行を保持できる必要があります。たとえば、箇条書きリストを入力しようとします。
ロバートK

ABSは恐ろしいプロポーションの怪物です。その90%は明らかに間違っています。
アダプター

そうではありませんという悪いです。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.