5 y [env_set.sh]# 環境変数の設定export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/hoge. 8 y 372K /etc/rc.d 36K /etc/udev/rules.d | sed ''というコードを実行してみてもらいたい。, と、このように挙動が異なる。最終行が改行コードで終わっていない場合、BSD版は改行を自動的に挿入し、GNU版はしないようだ。, 純粋なフィルターとして振る舞ってもらいたい場合にはGNU版の方が理想的ではあるが、すべての環境で動くことを目標にするならBSD版のような実装のsedも無視するわけにはいかない。このようなsedをはじめ、AWKやgrep等、最終行に改行コードが挿入されてしまうコマンドでの対処法を改行無し終端テキストを扱うというTipsにまとめたので見てもらいたい。, コマンドに関して迷ったらPOSIXのmanを見る。使用可能な正規表現については、正規表現メモさんの記述が 以下の例に、ターミナル ウィンドウと、さまざまなオペレーティング システムのシェル スクリプトで、環境変数を設定する方法を示します。ターミナル ウィンドウでの変数の設定は、そのウィンドウが開いている限り有効です。 シェルスクリプトとは、 上から順番にコマンドを実行する一種のプログラム です。設定ファイルにシェルスクリプト型式が取り込まれている理由は、それぞれの状況を考えて環境変数の設定がされるべきということがあります。 2 y tr '[A-Z]' '[a-z]' ← System V系での書式(この場合は運よくどこでも動く) もちろんシグナルの種類がこれだけしかないわけではない。ただ、 その他のシグナルは名称と番号が環境によってまちまち なのだ。(例えばSIGBUSは、FreeBSDでは10だが、Linuxでは7、といった具合), なので上記以外のシグナルを指定したい場合は名称("SIG"の接頭辞を略した文字列)で行うこと。使える名称自体は、POSIXの記述でもご覧のとおり、豊富にある。, killコマンドで-lオプションを指定すれば、使えるシグナルの種類の一覧が表示されるのはご存知のとおり。しかし、番号と名称の対応がこれで調べられるわけではない。Linuxだと丁寧に番号まで表示されるが、FreeBSDでは単に名称一覧しか表示されない(一応順番と番号は一致してはいるのだが)。, シェル関数の中で用いる変数を、その関数内だけで有効なローカル変数にする場合に用いる修飾子だが、これはPOSIXでは規定されていない。しかし、関数内ローカルな変数は簡単に用意できる。小括弧で囲ってサブシェルを作ればその中で代入した値は外へは影響しないからだ。, よって、中身を丸ごと小括弧で囲った次のシェル関数で定義したシェル変数$a、$b、$cは、関数終了後に消滅するし、外部に同名の変数があっても中の値を壊すことはない。, mktempコマンドはPOSIXで規定されていない! tr -d '[a-z]'' ← System V系での書式(これはBSD系、POSIX準拠実装ではNG) envというコマンドを実行すると、現在の環境変数の一覧が見れます。 LD_LIBRARY_PATHなど、いちいち設定するのが面倒な環境変数を、シェルスクリプトに記述できたら便利です。. シェル変数設定と同時に export する. UNIXでスクリプトを記述する場合、一番初めの行は #! -p display a list of all exported variables and functions, bash などのシェルでは、シェル変数の設定と同時に環境変数として export することが可能。 LC_ALL=C及びLANG=Cを設定し、ロケール環境変数を全てCロケールにして実行する。, '(chr);} # ←判定結果に応じて適宜選択される シェルスクリプトの良いところは簡単にスクリプトを作成できる点と環境を選らばずに利用できる点です。シェルスクリプトはシェルを使って動かすプログラムなので、シェルによっては動かない場合があります。 Help us understand the problem. $ export NEWENV="Hello" ←NEWENVを環境変数として設定 $ echo $NEWENV ←NEWENVの内容を表示 Hello ←NEWENVには「Hello」が設定されている 10 y 7 y END {if(ok==0){print "which: not found" > "/dev/stderr"; exit 1}}', 対処方法4の例「grepに無害なファイル/dev/nullを読み込ませる(推奨)」, xargs実装による違い(最初のprintfは"\\\'"という文字列を生成している), -- file unchanged  ← サイズが小さくならないので圧縮ファイルを作らなかった, プレゼントカレンダーに参加してMacBook Pro や ThinkPad をもらおう, you can read useful information later efficiently. 28K /etc/cron.daily 2.0K /etc/skel tr -d 'abcdefghijklmnopqrstuvwxyz', コマンドが存在すれば(パスが通っていれば)そのパスを返してくれるため、コマンドが無ければ無いなりにどの環境でも動くようなシェルスクリプトを書きたい時などに重宝するコマンドだ。しかし、このwhichコマンドがPOSIX標準ではないというオチが待っている。, しかし諦めることはない。POSIXに存在するcommandという名のコマンドに-vオプションを付けると似た動きをするのでこれを使うとよい。, 下記のコードをシェルスクリプトの冒頭に追記しておけば、whichコマンドが存在しない場合のみ、commandコマンドに基づいたシェル関数版whichが登録される。, command -vは組み込みコマンドが指定された場合でもコマンド名自身を返して正常終了するという点がwhichと異なるので、後ろのAWKで挙動を揃えている。, 単語が3つあるのだから、xargsはechoの後ろに“one”と“two”はもちろん、“three”も付けて実行してくれることを期待するが最後の“three”が無視されてしまっている。じつはこのxargs実装、最後の単語の後にも改行やスペース等の区切り文字を必要とするのである。, こういうxargs実装であっても確実に動作させるようにするには、例えばxargsの直前にgrep ^などを挿んでデータの終端に確実に改行が付くようにしてやることだ。, 標準入力から入ってきた文字列を引数にしてコマンドに渡すためのコマンドであるが、標準入力から空白以外が含まれた行が1行も渡ってこなかった場合、引数無しでコマンドを実行するxargs実装もあれば、コマンドを実行しないxargs実装もある。, xargsで呼び出される側のコマンドは引数0個で呼ばれるなど想定していない(Usageを表示したり戻り値0以外にしたりする)ものが多いので、前者の挙動の方が好ましいとは思うのだが、あるものはしょうがない。, 一応、前者の動作に揃える-rオプションというものがある(最近のFreeBSD版もこれを認識する)のだが、そんなオプションはPOSIXでは規定されていないがゆえ、それを付けて互換性を向上させようとすると逆に全ての環境で動く保証がなくなってしまうのが皮肉なところ。, 1番目の対処は、例えば呼び出すコマンドがrmなら-fオプションを付けてエラー扱いを抑止するという方法だ。, 2番目の対処は、例えば戻り値が0以外でも即エラー扱いしないとか、標準エラーに流れてくるエラーメッセージやUsageを/dev/nullに捨てるというものだ。, 3番目の対処は、例えば呼び出すコマンドがgrepなどのファイルを読み込むだけのものであれば使える方法だ。例えば/dev/nullを読み出しファイルとして、標準入力の最初(最後に付加すると改行なし終端テキストだった場合に不具合が起こる)に付加すればよい。, 4番目の対処は、手段が若干異なるだけで目的は3番目と同じだ。先程のgrepの例ならこう書き直す。短く書けるし、先程紹介した対処方法よりもお勧めだ。, grepコマンドの場合は特にこちらを勧める。理由は、grepコマンドは、検索対象のファイルが1個だけ指定された場合と複数指定された場合で挙動を変えるからだ。具体的には、検索キーワードが見つかった時、1個だけだった場合はファイル名を表示しないのに対し、複数個だった場合には行頭にファイル名を併記する。, 上記のように記述しておけば、grepコマンドは常に複数個指定されたと見なすので、findコマンドで見つかったファイルの数が1個であっても2個以上であっても、必ず行頭にファイル名を併記するようになり、動作が統一される。, xargsに\\\'という文字列を与えると、例えばFreeBSDのxargsとLinuxのxargsで異なった結果を返す。, 実はFreeBSDのxargsコマンドは、引数文字列を$@(ダブルクォーテーションなし)のように渡してシェルのエスケープ処理を受けるのに対し、Linuxの(GNU版の)xargsコマンドは"$@"(ダブルクォーテーションあり)のように渡すので、シェルのエスケープ処理を受けない。だから結果として、Linux上ではバックスラッシュが1個残るのだ。, ではどうするか。確実な方法は、エスケープ処理される文字を使わないことだ。バックスラッシュはいたしかたないとして、例えばシングルクォーテーションは\047などと表現した文字列がprintfに渡るようにすればよい。ただしバックスラッシュも、引数としてシェルに解釈される時やprintfに解釈される時などに変化を受けるので十分注意すること。, zcatは、gunzip | cat相当だと思っている人も多いかもしれないが違う! tr 'a-z' ← BSD系、POSIXでの書式, POSIXに準拠してないSystem V実装が悪いと言ってしまえばそれまでなのだが、歴史の上ではPOSIXよりも早いのでそれをいうのもまた理不尽というもの。ではどうすればいいか。, 答えは、「sedで代用する」だ。上記のように、全ての小文字アルファベットを消したいという場合はこう書けばよい。 シェルスクリプトは、シェルによって解釈・実行される一連の処理を記述したスクリプトです。主にUnix環境で使用されます。自動化、ショートカット、繰り返しなどに使えるため、作業を効率化できます。この記事では、基本知識や使い方を解説します。 ', 112K /etc/bash_completion.d bash などのシェルでは、シェル変数の設定と同時に環境変数として export することが可能。 このやり方をよく見かける気がしますが、他のシェルとの互換性の観点では別々に分けた方がよいかもしれません。 あまり意識されていないかもしれないが、シェルにおいて環境変数を設定するためには、以下の2ステップが行われる必要がある。 Why not register and get more from Qiita? シェルスクリプトを作成していると、設定変数が記述された設定ファイルを外部ファイルとして利用したい事がある。 そんな時、どのようにすればよいのだろうか? 1.外部ファイル(設定ファイル)で定義されている変数を利用する場合 12K /etc/abrt/plugins 私だけでしょうか、初めてこの設定の仕方を知った時、 PATHって、疑似的に永続化させてるだけなんだ・・・って悲しい気持ちになったのは. 環境変数名について 環境変数名は英数字を使うことができるが、英大文字と数字で構成するのが一般的である。英小文字は使えないわけではないが、シェル変数と区別がつきづらくなるためおすすめしない。 export コマンドはシェル変数を環境変数としてエクスポートするのに使用する。 変数名 自動的に設定される値 $# 実行時に指定された引数の数を表す変数。 「$ ./test.sh AAA BBB CCC」と実行された場合、シェルスクリプト test.sh 内で変数 $# を参照するとその値は 3 となる。 シェルスクリプト実行時、もしくは set コマンド実行時に指定された全パラメータが設定される変数。 What is going on with this article? 2.0K /etc/X11 (shebang)ではじめます。さらに、シェルスクリプトであることを明確にするためにコマンドをフルパスで記述します。シェルスクリプトでは、#!/bin/sh となります。Bourne shell の場合、初めの行が : (コロン)のみでもよいが、現在あまりこの記述は使われていない。また、#! 2.そのシェル変数を環境変数としてエクスポートする, export -p で表示される。 6.0K /etc/gss envコマンドで全てのロケールも含め環境変数を無効にした状態で実行する。, # 方法2. 環境変数を設定するためのコマンド.bash_profile. だから、実際に使えない環境がある。, でもシェルスクリプトを本気で使いこなすにはテンポラリーファイルが欠かせず、そんな時に便利なコマンドがmktempなのだが……。どうすればいいだろうか。簡易的な対処と本格的な対処の2種類を用意した。, 簡易的なもの(一意性のみでセキュリティーは保証しない)なら下記のようなコードを追加しておけば作れる。, mktempコマンドの有無を確認し、無ければコマンドと同じ使い方ができるシェル関数を定義するものだ。ただし引数は無視され、必ず/tmpディレクトリーに生成される。, POSIX版mktempコマンドを作ってしまったので、これをダウンロードして使えばよい。, 書式はCoreutils版に似せてある。ただし動作パフォーマンス確保のため、/binや/usr/binの中に元々のmktempが存在すればそちらを使う(execする)ようにしてあるので、あまり一般的でないオプションは使わない方がよい。, 「どの環境でも使える」という趣旨を理解せず、本投稿に寄せられた1番目のコメントの誘導には乗らない方がよい。, POSIXでも規定されている-wオプションであるが、環境によって挙動が異なるので注意。尚、-wオプションはPOSIXでデフォルト値が設定されているため、このオプションを記述しなくても同様の問題が起こるので注意!(POSIXの範囲ではないので参考までにということになるが、catコマンドの-nオプションではこの問題は起こらないようだ。), -wとは行番号に割り当てる桁数を指定するものであるが、問題は指定した桁数よりも桁があふれてしまった時である。溢れた場合の規定は定義されていないので、実装によって解釈が異ってしまったようだ。, 2つの実装を例にとるが、BSD版のnlコマンドでは、溢れた分の上位桁は消されてしまう。, 行番号数字の直後につくのはデフォルトではタブ("\t")なので、GNU版では桁数が増えるとやがてズレることになる。BSD版はズレることはない代わりに上位桁が見えないので、何行目なのかが正確にはわからない。, AWKコマンドの組み込み変数であるNRを使うとよい。さらに、次のようにしてprintf関数を併用すれば、GNU版nlコマンドと同等の動作をする。, 互換性を重視するなら、\xHHという16進表記によるキャラクターコード指定をしてはいけない。これは一部のprintfの独自拡張だからだ。代わりに\OOOという3桁の8進数表記を用いること。, Mac OS X等一部のOS上のprintfでは、\OOO(OOOは任意の8進数)と同等の表現として\0OOO(3桁数字の手前に数字の0が付いている)という表現も認められている。しかしこれが厄介な問題を引き起こす。, 例えば、\040に続いて数字の1を与えたかったら\0401と記述したいところだが、そうすると一部の環境では8進数で401に相当するコード(実際には0x01のStart Of Heading)を指定されたものと解釈してしまい、環境によって結果が変わってしまうのだ。, この問題を回避するには、直後に半角数字が続く場合、その数字自体も\049のようにエスケープするのが無難だろう。, 負の値を16進数に変換すると環境によって結果が異なる。例えば-1を16進数に変換すると次のとおりだ。, 従って負の値を16進数に変換するのはあまり勧められないが、どうしてもしたいなら下8桁のみを取り出すべきだろう。もちろんその場合、-2147483648より小さい値は扱えない。, 現在のpsコマンドは、オプションにハイフンを付けないBSDスタイルなど、いくつかの流派が混ざっているので厄介だ。, 「制御端末を持たないプロセスを含める」という働きであるが、このオプションは使わない方がいい。そもそもPOSIXのmanにはないし、GNU版とBSD版では解釈が異なるっぽい。, 例えばCGI(httpd)によって起動されたプロセス上で、-aも-xも付けず、自分に関するプロセスのみを表示しようとした場合、前者では表示されるものが後者では-xを付けた場合に初めて表示されるなどの違いがある。, 互換性を重視するなら、大文字である-Aオプションを用いてとにかく全てを表示(-axに相当)させる方がよいだろう。, -lオプションは、lsコマンドの同名オプションのように多くの情報を表示するためのものである。POSIXのmanにも記載されているし、実際主要な環境でサポートされているので使っても問題なさそうだが、使うべきではない。理由は、表示される項目や順序がOSやディストリビューションによってバラバラだからだ。, -lオプションを付けた場合の表示項目や順序がバラバラだと言ったが、実は付けない場合もバラバラだ。どの環境でも期待できる表示内容といえば、, くらいなものだ。互換性を維持しながらそれ以上の情報を取得しようとするなら、-oオプションを使って明確に表示させたい項目と順序を指定しなければならない。, -oオプションで指定できる項目一覧についてはPOSIXのman上の"STDOUT"セクション後半に記されている。(太小文字で列挙されている項目で、現在のところ"ruser"から"args"までが記されている), Linuxでは、親プロセスIDが0になるのはPID=1のinitだけだ。しかし、FreeBSD等では他の様々なシステムプロセスの親も0になっている。これは、psコマンドの違いというよりカーネルの違いであるが、互換性のあるプログラムを書くときには注意すべきところだ。, 2016年6月現在、Cygwinやgnupackで用意されているpsコマンドは残念ながらPOSIXのものとは非互換である。Windows配下で使うという事情により特別なものになっているようなのだが、-Aオプションも-oオプションもサポートされていない。manには記述があるのに使えないのは酷いと思うが仕方がない。, そもそもCygwinはPOSIX環境ではないからといって切り捨てるという考え方もあるのだが、対応をするのであればunameコマンドを使ってCygwinで動いていることを検出したら個別対応するコードにするしかない。, 試しにprintf 'Hello,\nworld!' SET コマンドは環境変数の値を参照したり、新しい値を設定したり、または削除するために使用します。書式は次の通りです。 いくつのかのオプションがありますが、それぞれ確認していきます。 なお環境変数とはOSが参照する設定を保存するためのものです。例えばコマンドを実行する時にどのディレクトリ探すのかを設定した PATH や、一時的な作業ファイルなどを保管するために使用するディレクトリを設定した TEMP などがあります。 コマンド実行時にシェルを指定し、そのシェルの引数に-lを渡してやることでログインシェルと同じ環境変数を実現する。 * * * * * /usr/local/bin/bash -l /usr/local/bin/cronjob sed 's/[a-z]//g', しかしながら、改行コードで終わっていないテキストデータを与えると改行を付け足してしまうsed実装があるので、そういう可能性のあるデータを扱いたい場合は更に対策が必要だ。→改行無し終端テキストを扱う, そこまでやるくらいだったら、範囲指定ではなく全部書いてしまえばいいと思うかもしれないが、もちろんそれでもいい。 シグナルの種類は名称と番号のどちらでも指定できるわけだが、番号で指定する場合、POSIXのmanによれば、どの環境でも使える番号は下記のもの以外保証されていない。え、たったこれだけ!? そのため、command の部分に指定するのはシェルスクリプトにしておいて、シェルスクリプトの先頭で必要な環境変数の設定を行い、その後いろいろなコマンドを実行するようにしておくのがよいだろう。 7 y ログイン時に読み込まれるbashの設定ファイル 9 y What is going on with this article? function arlen(ar,i,l){for(i in ar){l++;}return l;} 0.0206209, 'BEGIN{a=-2147483648;} # # 上の値を足してsigned long値を作る Why not register and get more from Qiita? シェルスクリプト実行時、もしくは set コマンド実行時に指定された全パラメータは変数 $@ と変数 $* に自動で設定される。 全パラメータのリストを取得する場合、どちらの変数を参照しても結果は同じであるが、ダブルクォート ( "" ) で囲んだ場合の動作が異なる。 私は毎時間crontabを実行しています。それを実行して.bash_profileいるユーザーは、ユーザーが端末からジョブを実行するときに動作する環境変数を持っていますが、実行時にcrontabによって取得されないことは明らかです。. 8.0K /etc/sasl2, 118K /etc/defaults By following users and tags, you can catch up information on technical fields that you are interested in as a whole, By "stocking" the articles you like, you can search right away. 144K /etc/ssh. Amazon ECS コンテナエージ… 4.0K /etc/statetab.d 生産性向上のための環境整備に関する記事を書いて、ThinkPad P14sをゲットしよう!, you can read useful information later efficiently. 1.シェル変数を設定する 0.020613 0.0205896 3 y tr 'A-Z' 'a-z' ← BSD系、POSIXでの書式 8 y {a+=$1;} # 環境変数(PATH,PAGER,EDITOR等) を設定する。 シェル変数(PS1 等)を設定する。 コマンドのalias(後述)を定義する。 ~/.bashrcの編集は慎重に ~/.bashrc を編集したら、一度、iTerm のウィンドウを問題なく開けるか、確 認すると良い。 便利。, Tips的な話だが、ファイルの行を最後の行から順番に(逆順に)に並べたい時はtacコマンドやtailコマンドの-rオプションのお世話になりたいところであろう。しかし、どちらも一部の環境でしか使えないし、もちろんPOSIXにも載っていない。ではどうするか……。そんな時は、次のTipsがお勧めだ。, どんな内容が与えられるかわからない文字列(シェル変数など)の内容を確認する時、最近のtestコマンドなら, と書いても問題無いものが多い(さすがに$strが"("だった場合ダメなようだが)。しかし、古来の環境では, というエラーメッセージが表示され、正しく動作しないものが多い。これは$strに格納されている"! /bin/sh というように #!の後に半角スペースを入れても動作する UNIX システムもあるが、互換性を考えると半角スペースは入れないほうがよい。 コメント行と改行 # 以降コ … 48K /etc/udev 今回のアップデートでは、新しい形式のタスク定義(環境変数をパラメータストアのパスから取得)が必要になるため、ECSエージェントの最新化が必須です。 ECS コンテナエージェンが1.22.0以上が必須のため、下記を参照にECSエージェントの更新を行いましょう。 1. それはGNU拡張であり、本来のzcatはuncompress | cat相当である。, 従って、次のようにしてgzip圧縮されたデータを与えるとエラーを返すzcatコマンド実装がある。, 全ての環境のzcatコマンドを想定するなら、compressコマンドで圧縮したデータを与えること。, ただし、compressコマンドは元データがファイルの場合、圧縮してもサイズが小さくならない場合に圧縮をしないので、次のような事故を起こさないように注意すること。(compress -fとすれば必ず作る), 困った時はすぐQiitaを始めとしたTipsを表面的に鵜呑みにし、使えそうなプロダクトを拾ってきてマニュアル通りに対応するプロダクト至上主義者達よ。そんなことでは、想定外の事態に見舞われた時すぐ死ぬぞ。想定外とは、マニュアルには載ってないから想定外なのだ。マニュアル通りにしか動けぬ者は、典型的なコンビニ店員の如く薄給に喘ぐだけ。頭を使え!UNIX哲学に目覚めよ!そしてPOSIX原理主義を崇拝せよ!. 9 y END{srand(a);print rand();}', # 方法1. 4.0K /etc/udev/makedev.d 環境変数IFSについて環境変数「IFS」(Internal Filed Separator)には、bashの場合「スペース」「タブ」「改行」($' \t\n')といった値が初期設定されていて、これらが文字の区切りとして認識されています … bashコマンドから起動することもできます。 「-v」オプションを利用すると全行エコー表示されます。 「-x」オプションを利用すると実行文がエコー表示されます。 「ファイルを直接実行」「bashコマンドで実行」とした場合、新しくシェルが起動されて実行されます。つまり、現在のシェルに影響を与 … 6 y 3 y By following users and tags, you can catch up information on technical fields that you are interested in as a whole, By "stocking" the articles you like, you can search right away. シェルでは、シュル変数によって変数を扱うことが出来ます。またシェル変数と演算子を使うことによって、複雑な処理の判定を行うことが出来るようになります。本記事では、シェル変数について解説し … 0 y シェル変数 (shell variable) : 現在利用しているシェル内でしか有効でない変数。他のプロセスには伝わらない。通常は小文字で書く。 環境変数 (environment variable) : 子シェルにも、その変数の内容を引き継ぐことができる変数。通常、大文字で書く。 1 y, 1 y 環境変数を設定する ※ はスペースを表してます。 説明 setenvコマンドは、cshので環境変数を設定するコマンドです。 コマンドを実行する際には「環境変数 値」という形式で 空白で区切って環境変数を指 … 4.0K /etc/gnats このやり方をよく見かける気がしますが、他のシェルとの互換性の観点では別々に分けた方がよいかもしれません。. 30K /etc/security $ ./env_set.sh$ echo $LD_LIBRARY_PATH$. 4.0K /etc/audisp 環境変数をうまく使う home user. CRing DCを利用するために必要な環境変数を設定します。 CRing DCを利用するための環境設定を行うために、以下のスクリプトファイルを提供しています。 4 y export. 環境変数を設定する方法. Help us understand the problem. さっそく、このシェルスクリプトを実行してみます。. 5 y という2つの書式がある。範囲指定の際にブラケット[~]が要るかどうかだ。BSD系の場合、ブラケットは通常文字として解釈されるので、これを用いると置換対象文字として扱われてしまう。しかしながら前者のブラケットは置換前も置換後も全く同一の文字なので幸いにしてどこでも動く。従って、このようなケースでは前者の記述をとるべきだろう。, しかし、-dオプションで文字を消したい場合はそうはいかない。 0.0205974 ロケール環境変数の設定値は環境によってまちまち ... 古いUNIX系OSで動かされる可能性も考慮した上でどの環境でも使えるシェルスクリプトにしたければ、iconvコマンドを使わないという方法を取らざる … "が、評価すべき文字列ではなく否定のための演算子と解釈され、そうすると後ろに左辺ナシの=が現れたと見なされてエラーになるというわけである。, testコマンドを用いて、全ての環境で安全に文字列の一致、不一致、大小を評価するには、文字列評価演算子の両辺にある文字列の先頭に無難な一文字を置く必要がある。, もっとも、単に文字列の一致、不一致を評価したいだけなら、testコマンドを使わずに下記のようにcase文を使う方がよい。上記のような配慮は必要ないし、外部コマンド(シェルが内部コマンドとして持ってる場合もあるが)のtestコマンドを呼び出さなくてよいので軽い。, このコマンドは各環境の方言が強く残るコマンドの一種で、無難に作るならなるべく使用を避けたいコマンドだ。, 例えばアルファベットの全ての大文字を小文字に変換したい場合、 恐らく、シェルスクリプトで設定した … 4.0K /etc/dracut.conf.d 環境変数入門. などとよく言われ、敬遠される。それなら共通しているものだけ使えばいいのだが、それについてまとめているところがなかなかないので作ってみることにした。, 「どの環境でも使える」とは、なかなか定義が難しい。あまりこだわりすぎると「古いものも含め、既存のUNIX全てで使えるものでなければダメ」ということになってしまう。しかし、私個人としては 今も現役(=メンテナンスされている)のUNIX系OSで使いまわせること にこだわりたい。, とはいっても全てのOSやディストリビューションについて調べられるわけではないので、この記事では基本的に最新のPOSIXで定義されていることをもって、どの環境でも使えると判断するようにした。(飽くまで「基本的に」ということで), 従って、互換性確保のため、シェルの中で使ってよい機能は Bourneシェルの範囲 ということにする。(bash,ksh,zsh,あるいはcsh等の拡張機能は使わないようにする), 新しいことを発見したり、教わったりしたら、随時この記事をバージョンアップしていこうと思うので、ツッコミ歓迎。, シェルスクリプトの最後の行だからといって、行末のLF(0x0A)を省略するのは止めるべきだ。それは環境によって異なる動作を引き起こす原因になり得る。, 例えば次のようにして、ヒアドキュメントセクションの終了宣言行で終わるシェルスクリプトを作ってみる。, コードを見ればわかるように最後の行にだけ行末にLF(0x0A)を付けていないわけだが、一部の環境でこれを実行すると次のようになってしまう。, ヒアドキュメントセクションの終了文字列と解釈されずに表示されてしまうのだ。他にも予期せぬ動作を招く恐れがあるので、最終行でもちゃんと行末には改行を付けよう。, シェルパターンとは、DOSで言うならワイルドカードといえば話が早いかもしれない。しかしUNIXのそれはもっと多機能で、ファイル名指定時のみならずcase文の条件指定時にも使えるし、何よりimage[1-9][0-9][0-9].jpgなどと指定すればそのディレクトリーの中に存在する、"image100"から"image999"までのファイルを一括指定できるなど、正規表現ほどではないにしろ表現力が高いことが特長だ。, しかしこのブラケットに要注意。ブラケット記号の中に列挙した文字「以外」を表す文字は、正規表現で馴染み深い^ではなく、!である。, ^は一応POSIXでも言及しているが、全ての実装で使えるとは限らない。この事実が厄介の元になっており、逆に言えば^を「以外」の意味として解釈する環境もあれば、通常文字としてそのまま解釈する環境もあるということだ。, 従って、シェルパターンにおけるブラケットの中で^自身を文字として指定したければブラケット内の2文字目以降に記述すべきである。, 変数の中身を部分的に取り出す記述に関して使っても大丈夫なものに関しては、POSIXのページ(2.6.2)を見るとまとまっている。, 例えばPIPESTATUSに依存したシェルスクリプトが既にあって、それをどの環境でも使えるように書き直したいと思った場合、実は可能だ。詳しいやり方については、別記事「PIPESTATUSさようなら」を参照してもらいたい。, これはAWK、grep、sed等、コマンドによっても使えるメタキャラは違うし、grepなら-Eオプションを付けるかどうかでも違うし、さらにGNU版でしか使えないものもあるので注意が必要。(*BSD上でもGNU版が採用されている場合もある。→grep参照), しかし、 正規表現メモ というスバラシいまとめページがあるのでここを見れば、使っても互換性が維持できるメタキャラがすぐわかる。, [[:alnum:]]のように記述して使う「文字クラス」というものがある。これは正式名称をPOSIX文字クラスといい、その名のとおりPOSIX準拠であるのだが、一部の実装ではうまく動いてくれない。(Raspberry PiのAWKなど), まぁ、それはPOSIXに準拠してないそっちの実装が悪いといってしまえばそれまでなのだが、そもそも設定されているロケールによって全角を受け付けたり受け付けなかったりして環境の影響を受けやすいので使わない方がよいだろう。, 乱数を求めたい時、シェル変数のRANDOMを使うのは論外。それなら、とAWKのrand関数とsrand関数を使えばいいやと思うかもしれないがちょっと待った!, 論より証拠。FreeBSDで次の記述を何度も実行してみれば、非実用的であることがすぐわかる。, つまり動作環境によっては乱数としての質が非常に悪いのだ。AWKが内部で利用しているOS提供のrand(3)とsrand(3)を、FreeBSDは低品質だったオリジナルのまま残し、新たにrandom(3)という別の高品質乱数源関数を提供することで対応しているのが理由なのだが。(Linuxではrand(3)とsrand(3)を内部的にrandom(3)にしている), ではどうすればいいか。POSIXで定義されているものではないが、/dev/urandomを乱数源に使うのが現実的だと思う。例えば次のようにしてod、sedコマンドを組み合わせれば0~4294967295の範囲の乱数が得られる。, 最後のsedは、なぜtr -Cd '0-9'にしないのか。理由は、→trコマンド参照, 乱数の品質は/dev/urandomほど高くないものの、代替手段はある。psコマンドの結果は実行するたびに必ず変化するのでこれを種として取り入れる。, 具体的には、プロセスID、実行時間、CPU使用率、メモリ使用量の各一覧あたりが刻々と変化するのでこれらを取得するとよいだろう。更に、現在日時も加え、これらに基づいて2^32未満の範囲でAWKのsrand()に渡す乱数の種を生成しているのが下記のコードだ。, コマンドによっては、ロケール環境変数(LANGやLC_*)の内容によって動作が変わるものがある(環境によっては変わらないものもある)。具体的に何が変わるかといえば、主に文字列長の解釈や、出力される日付である。下記にそれらをまとめてみた。, ロケール環境変数(LANGやLC_*)の内容によって、全角文字を半角の相当文字と同一扱いしたり、全角文字の文字列長を1とするもの, ロケール環境変数(LANGやLC_*)の内容によって、デフォルトのフィールド区切り文字のが変わるもの, ロケール環境変数(LANGやLC_*)の内容によって、出力される日付の書式が変わるもの, これも認識しておくべきことである。Linuxの多くのディストリビューションではインストール時に日本語を選択すると、日本語のロケールが設定されるが、皆が皆そうしているとは限らない。, 全ての環境で動くようにするのであれば、ロケール設定無しの状態、すなわち英語で使うべきであろう。, ロケール系環境変数には現在、LANGUAGEとLC_*とLANGがある。このうち各種LC_*についてはLC_ALLの設定によって全て上書きされるが、LANGには効かないのでLC_ALLとLANGを両方とも"C"にする。最初に列挙したLANGUAGEは最も強い効力を持つようだが、LANGやLC_ALLに"C"が設定されている場合は無視されるということである。→GNU gettextドキュメント2.3.3項, ちなみに、いにしえのexportは=を使えないということだが、今どきのPOSIXのmanによれば使えることになっている。, よく「exprを使え」というが、$((式))はPOSIXでも指定されているので使ってもよいものとする。, ただ、数字の頭に"0"や"0x"を付けると、それぞれ8進数、16進数扱いされるのでexprとの間で移植をする場合は気を付けなければならない。(exprは数字の先頭に0が付いていても常に10進数と解釈される), FreeBSD 9.xに標準で入っているAWKでは、-1*0を計算すると-0という結果になる。, ところがこの挙動は同じFreeBSDでも10.xでは確認されていないし、GNU版AWKでも起こらないようだ。, このようにして、0であっても-0という二文字で返してくる場合のある実装もあるので、0を1文字と決め付けていると不具合を起こす場合がある。, 頭に0が付いている数値を即値(プログラムに直接書き入れる値)として与えると、それを8進数と解釈するAWK実装もあれば10進数と解釈するAWK実装もある。, とやると、きちんと要素数(この例では3)を返してくれる。が、AWKの種類によっては、これに対応しておらずエラー終了してしまうものがある。, なので、例えば次のarlen()のように、配列の要素数を数える関数を自作してそちらを使うべきだ。, 幸いAWKの配列変数は、 参照渡し なので要素の中身が膨大だとしてもそれは影響しない。(要素数が大きい場合はやはり負担がかかると思うのだが……), 「length関数が使えるなら使いたい!」というワガママなアナタは、こうすればいい。, AWKの基本文法は、各行に対するパターンとそれにマッチした時のアクションの記述から成っている。そしてアクションは省略可能で、省略した場合は{print $0;}を指定されたものと解釈されることになっている。, しかし、アクションを省略するとエラーになってしまう実装がある。RaspbienやSolarisに載っているAWKでは次のようになってしまう。, 回避策は、パターンを単独の行で記述するか、パターンの直後にセミコロンを付ければよいが、ワンライナーでも使えるのは後者だ。, GNU版の独自拡張がいくつかあるが、中でも注意すべき点はgensub関数がそれであること。互換性を優先するなら多少不便かもしれないが関数とは言い難いインターフェースのsub関数やgsub関数を使う。あとは、GNU AWKの--posixオプションに関するまとめ@kbkさんのページを見ればだいたいよいと思う。, AWKの正規表現は、繰り返し指定が苦手。"? 11 y, 先頭が0で始まる3桁8進数による文字指定は、直後の文字によっては御変換されることがある, 文字列評価演算子の両辺にある文字列の先頭に無難な1文字を置けば、どこでも正しく動く, 'match($0,/^\//){print; ok=1;} 0.0206052 "(0~1個)と"*"(0個以上)と"+"(1個以上)は使えるが、2個以上の任意の数を指定するための{数}がない。GNU AWKにはあるんだけどね。その他は、正規表現メモさんの記述を見るのが便利。, 上記の例は、0x7FFFFFFF(符号付き4バイト整数の最大値)より大きい整数を扱えないAWK実装である。このようなことがあるので桁数の大きな数字を扱わせようとする時は注意が必要だ。, POSIXに明記されているはずのコマンドなのだが、残念ながら一部のOSでは最小構成インストールでは省略されているものがある。Debian系Linuxディストリビューションの一部(Raspbianなど)やCygwinで確認している。, どの環境でも使えるシェルスクリプトにしたければ、bcコマンドを使わないという方法を取らざるを得ない。ただし、さすがにPOSIXのコマンドだけあり、省略されるOSでも(apt等により)大抵パッケージとして用意されているので、コメントやドキュメントでbcコマンドをインストールするよう促すのも手であろう。, 元々の機能が物足りないが故か、各環境で独自拡張されているコマンドの一つだが、互換性を考えるなら使えるのは, の2つだけと考えるが無難だと思う。フォーマット文字列中に指定できるマクロ文字の一覧は、POSIXのmanの"Conversion Specifications"の段落にまとめられている。, いろいろあるのだけど、UNIX時間(エポック秒とも呼ばれるUTC 1970/1/1 00:00:00からの秒数)との相互変換は無いようで、これが非常に残念。これさえできれば何とでもなるのに……。, だがこんなこともあろうかと、相互変換コマンドutconvを作っておいた。もちろんシェルスクリプト製だ。詳しくは、シェルスクリプトで時間計算を一人前にこなすを参照してもらいたい。, 違いがわかるだろうか? この場合、シェルスクリプトのシェバンは無視され、必ず現在の環境下(bash)で実行されます。処理や実行結果が現在のシェル環境に反映されるので、主に設定ファイルの読み込みなどで使用されます。 ②「bash」コマンドで実行した場合 1列目(サイズ)が、前者は左揃えなのに後者は右揃えなのだ。なのでどの環境でも動くようにするには、1列目であっても行頭にスペースが入る可能性を考慮しなければならない。, 例えば1列目の最後に単位"B"を付加したいとしたら、下記の1行目はダメで、2行目の記述が正しい。, このようにして1列目にインデントが入るコマンドは結構あるし、インデントの幅も環境によりまちまちなので注意が必要だ。(例、 uniq -c 、wc などなど), 結論から言うと、どこでも動くようにしたい場合、下記の項目に1つでも当てはまる時はechoコマンドは使うべきではない。, 例えば、Linuxのechoコマンドは-e、-nオプションに対応しており、第一引数に指定すれば、それを文字列として表示せずに動作を変える。一方、FreeBSDのechoコマンドは-nのみに対応しており、また一方、AIXのechoコマンドはどちらにも対応していない。, 例えば\nは改行を意味するエスケープシーケンスであるが、FreeBSDのechoはそのまま“\n”と表示する。一方、Linuxのechoは-eオプションが付けられた時のみ改行に置換される。また一方、AIXのechoは常に改行に置換する。, AIXのechoはデフォルトでエスケープシーケンスを解釈するのだ。「それPOSIX的にどうなの?」と困惑するかもしれないが、POSIXのechoのmanにはちゃんとエスケープシーケンスの記述がある。, どんな文字列が入っているかわからない変数を扱う場合(ハイフンで始まらないとかエスケープシーケンスを含まないとわかっているならそのままでよい)、例えば次のようにprintfコマンドを使うなどして回避すること。, 今の環境変数の影響を一切受けずにコマンドを呼び出すために、env -i <コマンド名>のように-iオプションを使って起動したい場合があるが、ここで注意が必要だ。, 大抵の実装では呼び出すコマンドパスを見つけるまでは環境変数PATHを覚えていてくれる。しかし一部の実装では-iオプションを付けると、コマンドパスを見つける前に環境変数PATHの内容を消してしまい、指定したコマンド起動に失敗してしまうことがある。, この問題を防ぐには、既存の環境変数PATHを-iオプションの後ろで改めて指定するとよい。もちろんこの場合、環境変数PATHの値は呼び出し先コマンドに引き継がれることになるので注意すること。, 理由はというと、一部の環境のexecコマンドは、このようにして設定された環境変数を渡してくれないからだ。もしexecコマンド越しに環境変数を渡したいのであれば、事前にexportで設定しておくこと。, 一般的に、ファイル名として-を指定すると標準入力の意味と解釈されるが、本コマンドに対しては使わない方がよい。POSIXでもこのコマンドでもこのコマンドについて、そう解釈されると確かに書いてあるのだが、BSDの実装では真面目に"-"というファイルを開こうとしてエラーになってしまう。, 俺は*BSDを使っているから、grepだってBSD版のはず。ここで使えるメタキャラはどこでも使えるでしょ。, なんと、GPL排除に力を入れているFreeBSDのgrepはGNU版だ。関係者によれば、主に速さが理由で、grepだけは当面GNU版を提供するのだという。なので、POSIX標準だと思っていたメタキャラが実はGNU拡張だったということがある。(代表的なものは\+や\?や\|), POSIX標準grepで使える正規表現は、-Eオプション無しの場合には9.3 BREで規定されているものだけ。-Eオプション付きの場合には9.4 EREで規定されているものだけだ。正規表現メモさんによる日本語解説が分かりやすいかもしれない。, 大抵の環境には-cオプション(ファイルの先頭をバイト単位で切り出す)に対応しているのだが、POSIXでは規定されていないせいか正しく実装されていない環境も存在する。(AIXでは最後に余計な改行コードが付く), ちなみに、POSIXでもtailコマンドではきちんと規定されているので、headだけ規定されていないのはちょっと不思議だ。, さて、それでは-cオプションが使えない環境で何とかして同等のことができないものか……。大丈夫、ddコマンドでできる。, ddコマンドは標準エラー出力に動作結果ログを吐くので、head -c相当にするなら 2>/dev/null などと書いて、ログを捨てること。, POSIXに明記されているコマンドなのだが、初版より後に登場した新しいコマンドであり、一部のOSでは後から別途インストールしなければ使えない場合がある。比較的新しい実装としてはFreeBSD 9.0未満などが該当する。, 古いUNIX系OSで動かされる可能性も考慮した上でどの環境でも使えるシェルスクリプトにしたければ、iconvコマンドを使わないという方法を取らざるを得ない。ただし、さすがにPOSIXのコマンドだけあり、(port等により)大抵パッケージとして用意されているので、コメントやドキュメントでiconvコマンドをインストールするよう促すのも手であろう。, たまに、elseの時は何かしたいけどthenの時は何もしたくないということがある。そんな時、then ~ else の間に何も書かないとBash等一部のシェルではエラーを起こしてしまう。, elifの後もelseの後も同様であるが、Bashでは何かしら有効なコードを置かないといけないのだ。(コメントを書いただけではダメ), 何らかの無害な処理を書けばいいのだが、一番軽いのはnullコマンドではないだろうか。つまり、こう書けばどの環境でも無難に動くようになるだろう。, 別の対策としては、条件を反転してそもそもelse節を使わずに済むようにするのもいいだろう。, 実行中のホストに振られているIPアドレスを調べたい時にこのコマンドを使いたいことがあるが、各環境での互換性を確保するには2つのことに注意しなければならない。, 大抵の場合、ifconfigは/sbinの中にある。しかし 多くのLinuxのディストリビューションでは一般ユーザーにsbin系のパスが通されていない。 だから、このコマンドを互換性を確保しつつ使いたい場合は、環境変数PATHにsbin系ディレクトリー(/sbin、/usr/sbin)を追加しておく必要がある。, ifconfigから返される書式が環境によってバラバラである。そこで、IPアドレスを取得するためのシェルスクリプトを別Tipsとして書いてみたので参考にしてもらいたい。(IPv6も対応). 4.0K /etc/ppp シェルスクリプトなどで日本語コードを利用する場合,LANG(環境変数の1つ)で「ja_JP.ujis」などと指定しておく必要がある。 grep (GNU grep) 2.5.1-FreeBSD csh コマンドは、USER、TERM、HOME、PATH の各環境変数を、それぞれ csh 変数の user、term、 home、path にコピーします。 通常のシェル変数がリセットされると必ず、これらの値が環境に再びコピーされます。 path 変数は、.cshrc ファイル以外では設定できません。csh サブプロセスがパス定義を環境 … 逆に子の環境変数を親に引き継ぐには. 4 y 40K /etc/pam.d 環境変数とは、シェルの設定を行う特殊な変数です。 環境変数回りのトラブルはちょくちょくあるので、簡単に基本を説明しておきます。 envで環境変数を確認する. 6 y 基本的には、子の環境変数を親が使うことは出来ません。 試しにシェルスクリプト内で環境変数を定義してみますが、その環境変数は親のシェルでは有効ではありません。hoge2.shを作成し、テストしてみます。 シェルスクリプトで環境変数を設定する. 3.5 環境変数の設定. Copyright 1988, 1992-1999, 2000, 2001 Free Software Foundation, Inc. 1 y 2 y
大学 第二外国語 簡単, 子供 朝ごはん ワンプレート, アンティーク 服装 メンズ, Tiktok いいね欄 消す, 文系 就職 できない, キャロットラペ ツナ サンドイッチ, リカちゃん クローゼット 手作り 持ち運び, フリード エアコン 効き, ラジコン 飛行機 自作 パーツ, ワード 円グラフ 二つ並べる,