challenge 環境変数の取得

コマンドライン引数の取得がありましたが、今回は環境変数の取得をお願いします。

取得した内容を表示できればよいですが、可能でしたらキーから値を得る手段の実装もお願いします。

Posted feedbacks - Flatten

Nested Hidden

つまらない回答ですが。

1
2
3
4
5
#! /usr/bin/perl

foreach(sort keys %ENV){
        print "$_: $ENV{$_}\n";
}

環境を選ぶかもしれません。

環境変数名=値

という文字列の配列なので、strtokで分割。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[], char *envp[])
{
    char **p;
    char *name;
    char *value;

    for(p = envp; p != NULL; p++) {
        name  = strtok(*p, "=");
        value = strtok(NULL, "=");
        printf("%s = %s\n", name, value);
    }

    return 0;
}

Sys.getenv() で名前つきvectorの形式で環境変数の一覧を取得できます。

引数にキーを指定すると、特定の値のみを取得することもできます。

1
2
3
4
5
6
# 1. get all environment variables
Sys.getenv()
# 2. get all keys of environment variables
names(Sys.getenv())
# 3. get a specific environment variable
Sys.getenv("PATH")

もっともシンプルな例だと思います。

getEnvironmentは(環境変数名, 値)というペアのリストを返します。

printはリストをそのままプリントアウトすることができます。

1
2
3
import System.Environment

main = getEnvironment >>= print

ついでにC++とQtで。 QMapを返すものがあるのかとおもい、探してみましたけど、検索能力が低く、見つけることができませんでした。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include <QtCore>
#include <QtDebug>

#include <cstdlib>

int main(void)
{
        QStringList env = QProcess::systemEnvironment();
        QStringListIterator itr(env);
        QMap<QString, QString> envMap;
        while(itr.hasNext()) {
                QString str = itr.next();
                envMap[str.section('=', 0, 0)] = str.section('=', 1, 1);
        }

        qDebug() << envMap["PATH"];

        return EXIT_SUCCESS;
}

特にコメントなし、 誰が書いてもこんな感じでしょう。
1
2
3
System.getenv().each {
    println it
}

単純に。

1
(for-each print (sys-environ))

分かる範囲で対応してみました。
環境変数の取得に関しては、処理系依存ですが、大概の処理系には存在していて、統一的に扱えるようなラッパーのパッケージも存在しています。
環境変数一覧は、SBCL、CMUCL、Clozure CL、CLISP、Allegro CLに対応しています。
変数名からの値の取得は、SBCL、CMUCL、Clozure CL、CLISP、Allegro CL、ECL、LispWorksに対応しています。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
(asdf:oos 'asdf:load-op :arnesi)
(asdf:oos 'asdf:load-op :osicat)

(defpackage :doukaku-191 (:use :cl))
(in-package :doukaku-191)

;; 一覧
(defun env ()
  #+(or sbcl cmu openmcl) (osicat:environment)
  #+clisp (getenv)
  #+allegro (excl.osi:environment))

;; 変数名から値を取り出し
(defun getenv (name)
  #+ecl (sys:getenv name)
  #-ecl (arnesi:getenv name))

1
2
3
4
5
6
rem 環境変数の一覧を表示
set
rem 値の取得
echo USERNAME=[%USERNAME%]
rem ついでに設定
set FOO=bar

System.getenv メソッドで環境変数が取得できます。引数にキーを渡した場合は対応する文字列が、キーを指定しない場合は Map 型で全ての環境変数が返されます。

1
2
3
4
5
6
7
public class Sample {

    public static void main(String[] args) {
        System.out.println(System.getenv());
        System.out.println(System.getenv("USER"));
    }
}

 RubyではENVオブジェクトを使用して参照します。

1
2
3
4
5
#! /usr/bin/ruby

ENV.keys.sort.each do |key|
    puts "#{key}:\t#{ENV[key]}"
end

ghcを使ってコマンドラインからワンライナーで。

1
% ghc -e "System.Environment.getEnvironment"

PHPは$_ENVで環境変数を扱います。

1
2
3
4
5
<?php

foreach( $_ENV as $key => $val ) {
    echo $key.': '.$_ENV[$key].PHP_EOL;
}

Pythonでは、環境変数はos.environという辞書 (連想配列) でアクセスできます。

1
2
3
4
5
6
7
8
9
import os

# 辞書の全要素を順番に読み出し。
# kには変数名、vにはその値が入る。
for k, v in os.environ.iteritems():
    print k, v

# キーを指定して読み出し。
print os.environ["PATH"]

http://ja.doukaku.org/comment/6777/ をもとに、もうちょっと突っ込んで調べてみました。

getも不要のようですね。

1
2
3
4
5
6
7
// 一覧
System.env.each {
    println it
}

// 1件
System.env["USERNAME"]

D 2.0 + 標準ライブラリ (Phobos)、Linuxで動作確認。連想配列を作ってしまう方針で。
Phobosには環境変数APIが無いので、Cの environ(7) を直接呼び出します。
C文字列をDのstringに変換する処理が面倒ですね。もっとうまいやり方があるような気がする...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import std.stdio;
import std.string;
import std.c.linux.linux: environ;
import std.c.string: strlen;

void main()
{
    char** p;
    string[string] envAA;
    for (p = environ; *p != null; p++) {
        char[] key_and_value = (*p)[0 .. strlen(*p)];    // "FOO=BAR"
        int iEqual = key_and_value.find('=');    // index to '='
        string key = cast(string)(key_and_value[0 .. iEqual]);
        string value = cast(string)(key_and_value[iEqual + 1 .. $]);
        envAA[key] = value;
    }
    envAA.rehash;

    foreach(key, value; envAA) {
        writefln("%s: %s", key, value);
    }
    writefln("PATH = %s", envAA["PATH"]);
}

System.Environment.GetEnvironmentVariableメソッドで指定したキーの環境変数の値を取得出来ます。
System.Environment.GetEnvironmentVariablesメソッドで環境変数のキーと値がペアになったSystem.Collections.IDictionaryを取得出来ます。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
using System;

class Program {
    static void Main(string[] args) {
        //キーから取得
        Console.Write("環境変数を取得します。キーを入力して下さい。:");
        string key = Console.ReadLine();
        Console.WriteLine(Environment.GetEnvironmentVariable(key));

        //一覧を表示
        Console.Write("環境変数の一覧を表示します。");
        Console.ReadLine();
        foreach(string key_ in Environment.GetEnvironmentVariables().Keys) {
            Console.WriteLine("{0} = {1}", key_, Environment.GetEnvironmentVariables()[key_]);
        }
        Console.ReadLine();
    }
}

windows 用のコンソール版の場合です。
個々の環境変数は getenv で取得できるようですが、環境変数全体を
取得する方法が、わかりませんでした。存在しない変数名を指定すると
0 が返ります。
1
exit echo getenv 'tmp'

環境変数はosモジュールで提供されています。
Keyは引用符でくくった文字列を指定します。
1
2
3
4
5
%%全環境変数の表示
os:getenv().

%% キーを指定した場合
os:getenv(Key).

変数名から値を得るだけなら、getenv 関数があります。

1
2
3
4
5
private import std.stdio, std.process;

void main() {
    writeln(getenv("PATH"));
}

なでしこには「環境変数取得」「環境変数展開」の二つが標準命令にあります。
1
2
"PATH"の環境変数取得して表示
"%TMP%"の環境変数展開して表示

親OS上の環境変数の取得ということで、GhostScript 依存の getenv operator を使用しました。 PostScript の本来の環境変数(デバイス解像度等)は普通に currentdict 中に入っているわけで、普通に変数名だけで参照できるわけですが、マクロ等も一緒に入っているのでいわゆる変数一覧、というのは 膨大になると思います。後半のようにうっかり forall を使ってアクセスするとスタックがあふれたりとか....

1
2
3
4
5
6
7
%!PS

(PATH) getenv { = } if

% ========= Cut Here ===========
%!PS
currentdict { === } forall

env: ドライブを ls します。 ls は Get-ChildItem のエイリアスですので Get-ChildItem と書くほうがよいですね。 キーを指定する場合には env: ドライブのキーの項目を Get-Item します。

1
2
3
Get-ChildItem env:

Get-Item env:HOME

ども、raynstardです。
環境には依存しないと思いますが、
入力データを壊してしまうので基本的に直接strtok()は、
まずいいんじゃないでしょうか?
# forkとかexec*したときとか

このコードなら問題ないからやっているだけかもしれませんが。。。
ちょっと気になりました。

キーから値を得るにはSys.getenvを使う。
環境変数を全部取得するにはUnix.environmentを使う。
ちょっと紛らわしいけど、Unix.environmentはWindowsやcygwin環境でも使える。
以下のコードをコンパイルするには
$ ocamlc unix.cma hogehoge.ml
または
$ ocamlopt unix.cmxa hogehoge.ml
のようにunix.cma,unix.cmxaも一緒にコンパイルする必要がある。
1
2
3
4
5
(* show path *)
let v = Sys.getenv "PATH" in print_string v;;

(* show all enviroments *)
let e = Unix.environment () in Array.iter (Printf.printf "%s\n") e;;

Squeak Smalltalk で。

特定の値を得るには、返値に対してキーを指定してアクセス(#at:)します。

例: UnixProcess env at: #HOME

1
UnixProcess env

jclを使ってみました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import    scala.collection.jcl.Conversions

object PrintEnv {
    def printEnv:Unit = {
        Conversions.convertMap(System.getenv).keys.toList.sort { (a,b) => a < b }.foreach { k => printEnv(k) }
    }
    def printEnv(key:String):Unit = {
        Console.printf("%s:\t%s\n", key, System.getenv(key))
    }
    def main(args:Array[String]):Unit = {
        PrintEnv.printEnv
    }
}

 JavaFXScriptで。

1
2
3
4
5
import    java.lang.System;

for (k in System.getenv().keySet()) {
    System.out.printf("%s\t%s\n",k,System.getenv(k));
}

表示できればよいとの事なので、見やすさは考慮しません :-D
1
print %ENV;

bashで、exportされてないシェル変数を避けて環境変数の一覧を表示する方法には「printenv」「env」「export -p」があります。このうちexportはbash内蔵コマンドです。

特定のキーから環境変数の値を得るには、printenvに環境変数名を与えます。

蛇足として、内蔵コマンドだけで「printenv 変数名」相当のことをするコマンド(関数)を定義してみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 環境変数一覧は以下のどれかで
printenv
env
export -p

# キーから値を得るには、printenvで
prinetnv 'HOME'

# printenvは外部コマンドだからという方には、pure bashで
myprintenv1() {
    local name=$1
    local a b str
    export -p | while read a b str;do
        if [ ${str%%=*} = "$name" ];then
            str=${str#*=\"}
            echo ${str%\"}
            break
        fi
    done
}

Index

Feed

Other

Link

Pathtraq

loading...