bashスクリプトの「read」の変数は未定義です


0

i3wm画面モード(外部画面、内部画面、すべて、またはミラー)を切り替えるために使用するこのbashスクリプトがあります。スクリプトの最初の部分は、画面の名前を取得します。次の部分をコピーして端末で実行する場合:

#!/bin/bash

xrandr|grep " connected primary"|IFS=" " read INTERNAL_OUTPUT con
xrandr|awk '/ connected/ && !/ primary/'|IFS=" " read EXTERNAL_OUTPUT con
echo internal monitor is $INTERNAL_OUTPUT
echo external monitor is $EXTERNAL_OUTPUT

...

私は次のようなものを得ます

$ ./script.sh
internal monitor is eDPI
external monitor is DPI-1

しかし、実際のスクリプトを実行すると、変数は空になり、表示されるのはすべて

$ ./script.sh
internal monitor is 
external monitor is 

スクリプト内で変数を設定するときの違いは何ですか?


1
echoコマンドがコマンドと同じスクリプト内にある場合、readそれらは機能するはずですが、./ sourceコマンドで呼び出さない限り、スクリプトの外部では機能しません。
AFH

どういう意味か分かりません。エコーを含む、スクリプト内のすべてが、動作しません。変数はまだ空です。
ecc

その場合、端末からどのように機能するかわかりません。それを機能させるための唯一の方法はでxrandr|grep " connected primary"|{ IFS=" " read INTERNAL_OUTPUT con; echo internal monitor is $INTERNAL_OUTPUT; }、他のモニターでも同様です。これは、端末とスクリプトの両方で機能します。
AFH

2
ターミナルでも私には機能しません...仮説:これは機能せずbash、あなたのコンソールは機能しないのでbash(そこで機能します)(何と言っていls -l /proc/$$/exeますか?) bashルールを使用しているため、コードが失敗します。
キセノイド

変数を設定する場合はbash、次のようなものが必要ですINTERNAL_OUTPUT=$(xrandr|grep " connected "|grep -o '^[^ ]*')。これによりINTERNAL_OUTPUT、スクリプト内の後続の行で使用可能になりますが、で呼び出されない限り、端末に戻る際には使用できません.。スクリプトを呼び出さずに現在のシェルで変数を設定するには.、関数としてコード化する必要があります。
AFH

回答:


2

パイプラインで変数を設定したり、パイプの外部で値を使用したりすることはできません。パイプラインを実行する場合、各パーツは独自のサブシェルで実行されるため、readコマンドは独自のサブシェル内にあります。サブシェルは親の環境を変更できないため、そこに設定した変数は親が使用できません。

これを回避するには、@ AFHが言うようにコマンドを変更して、必要なものだけが出力されるようにし、それを親シェルの変数に割り当てます。

または、コマンドを再構築して、読み取りにパイプが入らないようにすることもできます。AFHのアプローチを好むが、並べ替えは次のようになります。

IFS=" " read INTERNAL_OUTPUT con < <(xrandr|grep " connected primary")

ここではread、コマンドの残りを実行するプロセス置換からの入力をリダイレクトするためread、まだ親シェルにあります。

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