3

ファイルに書かれているように、変数名の代わりに、ファイルを cat したときに変数値をきれいな方法で取得することは可能ですか。説明するのは難しいですが、簡単な例を次に示します。

$ cat <<EOF
$HOME
EOF
/home/myself

シェルによって既に展開されているため、 cat は /home/myself を返します。

$ echo \$HOME >/tmp/home
$ cat /tmp/home
$HOME

cat は単にファイルを読み取ります。ファイルには変数名が含まれるため (HOME=/home/myself とは異なり)、$HOME を cat によってここで何らかの方法で展開する必要があります。

私の質問は、これが何らかの方法で可能かどうかです。そうでない場合は、汚いコードを書く必要があります。

編集:それらは含む大きなxmlファイルです

<checkbox active="$value">

正しいか間違っているか

4

4 に答える 4

2

これを Python で試すのは簡単で、うまくいくかどうかを確認してください。re.sub関数を使用して"\$\w+"、(特定の文字列を置き換えるのではなく) 変換を行う関数を呼び出すなど、特定のパターンのすべての出現箇所を置き換えることができます。置換関数にはos.getenv()、もちろん変数名を取り、その値を返す を使用できます。

編集: 上記を実行する完全な Python スクリプトを次に示します。

#!/usr/bin/python

import fileinput
import os
import re

def transform(match):
    return os.getenv(match.group(1)) # replace the "capture" to omit $

for line in fileinput.input(): # reads from stdin or from a file in argv
    print re.sub('\$(\w+)', transform, line), # comma to omit newline
于 2011-05-17T01:57:20.970 に答える
1

cat少なくとも元の (第 1 版 UNIX) 形式で、入力を変更せずに出力にコピーします。最初から選択肢はありませんでした。その後、BSD が大量に追加し、元の UNIX チームは反対しました: 'cat旗を振ってバークレーから戻ってきました' (参照: 1 - passim)。ファイルの編集には使用しないでください - それはその目的ではありません。(私は、BSD (Mac OS X) の man ページで次の記事への参照を見つけましたcat: Rob Pike、「UNIX スタイル、または cat -v は有害であると考えられる」、USENIX Summer Conference Proceedings、1983 年。http://quotes も参照してください。 cat-v.org/programming/ )

catですから、仕事をする以外に何かが必要です。Perl または Python をお勧めします。どちらでも簡単にできます。sedまたは、 、またはおそらくを検討してawkください。

#!/usr/bin/env perl
use strict;
use warnings;
while (<>)
{
    foreach my $key (keys %ENV)
    {
        s/\$$key\b/$ENV{$key}/g;  # $envvar
        s/\${$key}/$ENV{$key}/g;  # ${envvar}
    }
    print;
}

これは入力行をループし、各環境変数を順番に探します。別のメカニズムは、可能な変数を探して、関連する置換を行うことです。これは少しトリッキーですが、実行可能です。

#!/usr/bin/env perl
use strict;
use warnings;
while (<>)
{
    while (m/\$((\w+))/ || m/\$({(\w+)})/)
    {
        my $key = $2;
        my $var = $1;
        s/\$$var/$ENV{$key}/g if defined $ENV{$key};
    }
    print;
}

キャプチャにリテラルを含める$と、置換操作が正しく機能しませんでした。

于 2011-05-17T02:43:46.463 に答える
1

これを行う明白な方法には、多くの問題があります。

# これは特定の入力で失敗します。HTMLは確かに問題になります
# '<' および '>' 文字はファイル リダイレクトとして解釈されるため
$ 読み取り中 r; do eval echo $r; 完了 < 入力

次の perl は、単純な入力の問題をかなりうまく処理するはずです。

$ perl -pwe 'while(($k,$v) = each %ENV ) { s/\${?$k}?/$v/ }' 入力

しかし、${FOO-bar} のような構造では何もしません。このような構成を処理する必要がある場合は、すべてのシェル メタ文字をエスケープし、while/read ループを実行するだけで十分な場合があります。

$ sed -e 's/\([<>&|();]\)/\\\1/g' 入力 | 読み取り中 -rl; do eval echo "$l"; 終わり

これは堅牢でも安全でもないことに注意してください。次のような入力で何が起こるかを考えてみましょう:

\; rm -rf /

「検討します」と言いました。それをテストしないでください。sed はセミコロンの前にバックスラッシュを挿入し、eval は文字列 "\\;" を取得します。これは、単一のバックスラッシュとそれに続くエコーを終了するセミコロンとして解釈され、rm -rf が実行されます。未知の入力を評価することの不安を考えると、perl のようなものに固執し、目的の sh 構造を明示的に置き換える方がおそらく安全でしょう。何かのようなもの:

$ perl -pwe 'while(($k,$v) = each %ENV ) { s/\${?$k}?/$v/ };
    s/\${[^-]*-([^}]*)}/$1/g' 入力

これは ${FOO=some-text} のような入力に問題があります。sh コンストラクト (${word:rhs} のすべてを確実に取得するには、「:」は「-」、「?」、「=」、「+」、「%」、「#」またはコロンを前に付けた同じもの (または、非 posix sh 構文を許可する場合は他の多くのシンボル!)) を使用すると、かなり複雑な比較セットを作成する必要があります。

于 2011-05-17T13:08:20.377 に答える