「オリジナル」を読みやすくするためにフォーマットしようとしました。そこから何が起こっているのかを説明しようとします:
PYTHONPATH=/my/extra/python/modules \
python /my/eclipse/plugins/org.python.pydev_*/PySrc/interpreterInfo.py 2>/dev/null |
sed '
s/INS_PATH$//g;
s/OUT_PATH$//g;
s/^EXECUTABLE:/Executable\\:/g
' |
tr -d '\n' |
cat \
<(
echo -en 'eclipse.preferences.version=1\nINTERPRETER_PATH_NEW=Name\:python\:EndName\:'
) \
- \
<(echo '&&&&&') \
>/my/workspace/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.python.pydev.prefs
それでは、このセクションごとに見て、意味を理解しましょう。完全を期すために、すでに知っていると思われる部分を含め、すべてを説明します。
PYTHONPATH=/my/extra/python/modules \
これは変数を設定していますPYTHONPATH
。コンテキストから、モジュールを探す場所をpythonに伝えると思います。コマンドと同じ「行」内で指定しているため、次の 2 つのことが起こります。
- 変数は自動的に環境にエクスポートされます
- 変数は、実行されている個々のコマンドに対してのみ設定されます (つまり、パイプライン全体ではなく、「最初の」コマンドのみであり、後のコマンドで使用するシェルの環境にはありません)。
次に、メインコマンド:
python /my/eclipse/plugins/org.python.pydev_*/PySrc/interpreterInfo.py 2>/dev/null |
ここで「python」インタープリターが実行され、interpreterInfo.py
実行するスクリプトが渡されます。
これは、必要_*
な特定のバージョンを指定していないことを意味しますorg.python.pydev
(1 つのバージョンのみが検出され、すべてのバージョンが同様に動作すると想定されています)。
これ2>/dev/null
は、通常、エラーとデバッグ情報がパイプされる stderr の出力が無視される (どこにもパイプされない) ことを意味します。
今それの肉:
sed '
s/INS_PATH$//g;
s/OUT_PATH$//g;
s/^EXECUTABLE:/Executable\\:/g
' |
これは 3 つのことを行います。最初の 2 つは似ています:INS_PATH
とOUT_PATH
は行末から削除されます。次に、お尋ねの最初の部分の:
文字が に置き換えられ\:
ます。なぜダブル\\
if\:
がゴールなのですか?ほとんどの場合、これはペダントリーによるものです。しかし\:
は有効なエスケープ シーケンスではなく、ほとんどsed
の s はエスケープ シーケンス\
の開始を示すリテラルとして解釈します。したがって、シーケンス の場合、 として指定されます。sed
\
\\
\:
\\:
これら/g
の各置換コマンドの最後の は、「グローバルに置換する」ことを意味します。つまり、最初だけでなく、一致が見つかるたびに。
次の行は簡単です。
tr -d '\n' |
これにより、出力内のすべての改行が削除されます。私が正しく理解している場合、これにより\:
、1行にパスの個別のリストが表示されます。
説明が必要な部分に戻る:
cat \
<(
echo -en 'eclipse.preferences.version=1\nINTERPRETER_PATH_NEW=Name\:python\:EndName\:'
) \
- \
<(echo '&&&&&') \
>/my/workspace/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.python.pydev.prefs
それは一度にたくさんのことを経験することです。要約しましょう:
cat input-one input-two input-n > output
cat
複数の入力を単一の出力に結合 (「連結」) します。これは実際にはコマンドの意図された使用法ですが、単一の入力cat
を出力するために使用されることがはるかに多いことがわかります。cat input-one
<( some-command )
some-command
その出力を実行してファイル記述子にリダイレクトします。そのパス ( /dev/fd/N
) は、元のコンテキストで引数として使用されて渡されます<( ... )
。たとえば、 とcat <( echo foo )
のようなコマンドを実行し、出力をファイル記述子にリダイレクトして読み取ります。による。直接実行した場合と同様に、出力はです。cat /dev/fd/64
echo foo
echo foo
64
cat
foo
echo
次に、次の 2 つを組み合わせます。
cat <( some-command ) some-input <( some-other-command )
これにより、 の出力some-command
、 のコンテンツsome-input
、および の出力がsome-other-command
1 つのストリームに結合されます。作業しているスクリプトでは、これらはすべて 1 つの出力ファイルに結合されています。
では、この出力用に実際にビルドされているコンテンツはどうでしょうか? それも行ごとに見てみましょう。
<(
echo -en 'eclipse.preferences.version=1\nINTERPRETER_PATH_NEW=Name\:python\:EndName\:'
)
これはリテラルを出力します:
eclipse.preferences.version=1
INTERPRETER_PATH_NEW=Name\:python\:EndName\:
echo -e
「バックスラッシュエスケープシーケンスを解釈する」ことを意味するため\n
、改行に展開されます。echo -n
「出力を改行で終わらせない」ことを意味するため、次に来るものはすべて同じ行の一部です。この場合、次に連結されるものは何でも行の一部になることを意味しINTERPRETER_PATH_NEW=
ます。
-
A-
は「標準入力から読み取る」の省略形であり、単独で実行する場合のデフォルトですcat
。多くのコマンドはこの省略形を使用しますが、そうでないコマンドの場合、これを指定する別の方法は です/dev/stdin
。これは、「このコマンドにパイプされたものを読み取る」ことを意味します。つまり、 からの出力で、デフォルトtr
で からの出力sed
を読み取り、デフォルトで からの出力を読み取りますpython
。
<(echo '&&&&&')
&
これにより、5文字と改行でストリームが終了します。この理由は実際にはわからないので、誰かがコメントして私を埋めてくれるかもしれません。
>/my/workspace/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.python.pydev.prefs
>
最後のステップとして、すべての出力が (シンボルを介して) ファイルにリダイレクトされますorg.python.pydev.prefs
。
何が起こっているのかを大まかに説明したので、今度はあなたが尋ねていた厄介な詳細に答える時が来ました。
なんで全\
キャラ?
\
sed 内でエスケープしたのと同じ方法で:
、ファイル内でもエスケープしてい.prefs
ます。ファイル内の sed 内でリテラルを指定するのと同じように、「リテラル」を意味\:
するようです。.prefs
:
\\
\
/
キャラクターはどうですか?
/
UNIX システム (最新の Mac OS、つまり OSX を含む) のディレクトリ セパレータです。Windows システムでは、\
が使用されます。多くの言語では、上記のように\
はエスケープ文字としても使用されるため、リテラルを指定するには、 のように\
記述する必要がある場合があります\\
。これには難しいルールはありません。この問題を認識している一部のクロスプラットフォーム言語では、/
Windows でもディレクトリ セパレータとして使用できます。
これで問題が解決することを願っています。他に説明が必要なことがあればお知らせください。回答を編集して追加情報を追加します。