Shell Script ライトクックブック

キーフレーズ

コマンド シェルスクリプト POSIX レシピ sed 文字列 ファイル print HTML AWK grep CGI echo awk name オプション Web printf 郵便番号 原理主義 環境変数 cat UNIX コード txt div tmp 場合 https 変数 ダブルクオーテーション 文字 データ file pipestatus html exit HTTP http session class JSON substr シェル sort github bin Ajax Cookie return () master CSV 改行 ソースコード dev 正規表現 ロケール URL GNU etc mktemp BEGIN .com text XML GET セッション ディレクトリー 変換 環境 テキスト スペース org while タイムスタンプ ファイル名 問題 Tukubai read POST n/ JavaScript 使える com false value type FreeBSD mkfifo SELECT null str cgi xhr Content public opengroup 指定 参照

目次ページ

レシピ 2.5 sed の N コマンドの動きが何かおかしい GNU 版でまた別のヘンな動きをする。 解説 33 問題文で示された sed コマンドは「元データの 3 行目に関しては、読み込んだら次の行も追加で読み込み、そ の際残った改行コードを“ー”に置換してから出力せよ」という意味である。もっとわかりやすく言えば「 3 行目 と 4 行目はハイフンで繋げ」という意味である。従って、正常な動作であるなら次のようになるはずである。 $ seq 1 10 ー sed ' 3 , 4N ; s/*n/-/g' ロ 1 2 3 ー 4 5 6 7 8 9 10 ところが、 FreeBSD 9. I-RELEASE の sed では次のようになってしまう。 $ seq 1 10 ー sed ' 3 , 4N ; s/*n/-/g' ロ 1 2 9 10 ←これは ←おかしい ! この問題はその後、修正コードと共にバグとして報告され、執筆時の最新版である FreeBSD 10.1 では修正さ れている。従って、 9. x や 10. x を使っているなら OS を最新版にアップグレードすることをお勧めする。もしそ れが難しいのであれば GNU 版を使うこともやむを得ないだろう。 GNU 版にも別のバグが ただし GNU 版にも同じ N コマンドでまた別のバグが見つかっている。 GNU 版の独自拡張である、行番号の相対表現を使うと・・

利用者の陰に潜む、様々な落とし穴 34 $ seq 1 10 ー gsed ' 3 , + 3N ; 1 2 9 10 これはおかしい ! 第 2 章 でも一部の文字が化けてしまう。どうすればよいか。ただし、標準入力は他のデータを渡すのに使っており、 AWK に値を渡したいのだが、 -v オプションで渡しても、シェル変数を使ってソースコードに即値を埋め込ん 問題 レシピ 2.6 標準入力以外から AWK に正しく文字列を渡す つかるかもしれない。 sed で N コマンドを使っているソースコードでもしおかしな動きをしていたら、 sed を疑ってみると原因が見 は執筆時に取得できた最新版 ( 4.2.2 ) でも残っていた。 やはりおかしい。 3 行目から十 3 行目までだから 7 行目と 8 行目が結合されてはいけないはずだ。ちなみにこれ 使えない。 awk —v "s=$str" 'BEGIN{print s} ' means awk ' BEG 工 N{print 回答 ←渡したい文字列 ← \ n がうまく渡せない ← *n も一 " もうまく渡せない ( 工ラーにもなる ) 環境変数として渡し、 AWK の組込変数 ENVIRON で受け取る。問題文の "*n means ー いのであれば、 こう書けばよい。 str='*n means "newline" ' awk 'BEGIN{print ENVIRON["str"] } ' newline ー ”を渡した 既にシェル変数に入っているのであれば export して環境変数化してから渡してもいいし、それが嫌ならコマン ドの前に仮の環境変数 ( 例えば "E ” ) を置いて渡したり、 env コマンドで渡してもいいだろう。

レシピ 2.6 標準入力以外から AWK に正しく文字列を渡す Str= export str awk 'BEGIN{print ENVIRON["str"] } ' E=str awk 'BEGIN{print ENVIRON C"E"] } ' env E=str awk ' BEGIN{print ENVIRON C"E"] } , 解説 何らかの事情で AWK に値を渡したいとなったら、手段はいくつかある。 1. ー v オプションで AWK 内の変数を定義して渡す 2. AWK のコードに埋め込んで即値として渡す 3. 標準入力から渡す 4. 環境変数として渡す 35 1 番目は定番で、 2 番目も ( 筆者は ) よくやる方法だ。だが、バックスラッシュを含む文字が化けるという問題 がある。 2 番目に関しては問題文に示したように、ダブルクオーテーションを含む場合に単純な文字化けでは済 まず、セキュリティーホールを生みかねない誤動作を招く。従ってこれらの方法はどんな文字が入っているかわ からない文字列を渡すのには使えない。 3 番目の標準入力を使えれば安全なのだが、メインのデータを受け取る ために既に使用中という場合もある。そうなると残る選択肢が 4 番目の環境変数というわけだ。 AWK は起動直後、環境変数を "ENVIRON ”という名の組込変数に格納してくれる。これは連想配列なので 環境変数名をキーにして読み出す。通常はこの変数によって現在設定されているロケールやコマンドバスを知る のに使うところだが、もちろんユーザーが自由に環境変数を定義してもよい。しかも都合の良いことに、一切工 スケープされることなく伝わる。例えばこのようにして、シェルの組込変数 IFS*5 を伝えることもできる。 $ ifs="$IFStI awk 'BEGIN{print " ( " ENVIRONCI'ifs'I] ")",1ength(ENVIRON["ifs"]) } ' ロ ←その直後に変数のサイズ ( 文字数 ) が 3 であると表示された。 ←括弧の中に空白、タブ、改行が表示され、 どんな文字が入っているかわからない文字列を安全に渡したい場合に知っておきたい手段だ。 * 5 文字列の列区切りと見なす文字列を定義しておく環境変数。 f 。 r 構文等で参照される。 行コードが入っている。 デフォルトでは半角スペースとタブ、そして改