シェルスクリプト総合 その20
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
2012/06/08(金) 00:35:51.19スクリプトのお勉強・自慢・腕試しなどにどうぞ。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
Linuxユーザは/bin/shの正体がbashなので特に注意。
FreeBSDユーザは/bin/shの正体がashなので注意。
v7 shに一番近くて、現役のshは、OpenSolaris由来のheirloom sh。
http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/sh/
http://heirloom.sourceforge.net/sh.html
・csh/tcshのシェルスクリプトは推奨されません。
(理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
manや参考リンクを見ましょう。
aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
前スレ
シェルスクリプト総合 その19
http://toro.2ch.net/test/read.cgi/unix/1323515200/
0092名無しさん@お腹いっぱい。
2012/06/16(土) 09:05:43.92GNU依存乙
0093名無しさん@お腹いっぱい。
2012/06/17(日) 08:29:54.78完全に陥落しました
0094名無しさん@お腹いっぱい。
2012/06/17(日) 14:58:07.56どんな時に便利っすか
0095名無しさん@お腹いっぱい。
2012/06/17(日) 15:13:21.090096名無しさん@お腹いっぱい。
2012/06/17(日) 17:40:13.730097名無しさん@お腹いっぱい。
2012/06/17(日) 17:51:43.630098名無しさん@お腹いっぱい。
2012/06/17(日) 17:52:22.830099名無しさん@お腹いっぱい。
2012/06/18(月) 09:39:45.83env TZ=JST+15 date
n=5
date -v -${n}d
0100名無しさん@お腹いっぱい。
2012/06/18(月) 12:19:00.380102名無しさん@お腹いっぱい。
2012/06/19(火) 00:23:33.590103名無しさん@お腹いっぱい。
2012/06/19(火) 01:23:21.92世界にはタイムゾーンがいくつもある、という事をよく分かっていない人が
そういう手法を取る結果、スクリプトがおかしな動作をする
…というところから、GNU版dateの拡張は始まっている
NetNewsがまだ生きてた時代の話
0104名無しさん@お腹いっぱい。
2012/06/19(火) 09:28:29.09サーバは1ヶ所にあって世界中を旅するわけではないので。
0105名無しさん@お腹いっぱい。
2012/06/19(火) 11:04:50.480106名無しさん@お腹いっぱい。
2012/06/19(火) 11:28:22.18何かおかしいか?
0107名無しさん@お腹いっぱい。
2012/06/19(火) 11:43:09.74笑い事じゃあないぞ
0108名無しさん@お腹いっぱい。
2012/06/19(火) 11:51:13.75django1.4もmultiple time zoneが入ったばかり。
default time zoneもcurrent time zoneも取得できる。
夏時間と遠隔地絡んだ特殊な処理も標準的にできるようになった。
またWebAppサーバのdefault time zoneはサーバの物理的な位置に合わせていると限らない。
まあシェルスクリプトの領分ではないが。
0109名無しさん@お腹いっぱい。
2012/06/19(火) 12:02:54.39sshした時にTZはクライアントのがいいか、サーバのがいいかなんて一意には決められないね。
環境変数TZは、最小限の手間でその辺のことうまく扱ってるね。
0110名無しさん@お腹いっぱい。
2012/06/19(火) 19:27:08.84エスポレル共和国時間で12時間前の時刻を計算したいときって、どうすればいいの?
0111名無しさん@お腹いっぱい。
2012/06/19(火) 19:33:35.80エスポレル共和国ってどこだか知らないけど、
タイムゾーンはどうなってるの?
0112名無しさん@お腹いっぱい。
2012/06/19(火) 19:34:09.40いったんログアウトしてエスポレル共和国のマシンで好きにやったらいいじゃんw
0113名無しさん@お腹いっぱい。
2012/06/19(火) 20:07:19.80$ env TZ='エスポレル共和国のタイムゾーン' date --date='12 hours age'
でいいんじゃない?
GNU date依存嫌ならepoch time計算して。
0114ワラ
2012/06/19(火) 20:11:25.700115名無しさん@お腹いっぱい。
2012/06/19(火) 21:34:29.04でもそのスクリプトだと、別のタイムゾーンのどこかの国からアクセスした場合でも
アクセス元ではなく、常にエスポレル共和国の計算結果が出てしまうのでは
0116名無しさん@お腹いっぱい。
2012/06/19(火) 22:00:52.43それはsshのサーバ/クライアントの設定で環境変数TZを引き渡せるように
AcceptEnv/SendEnvやPermitUserEnviromentするぐらいしかないんじゃなかろうか。
0117名無しさん@お腹いっぱい。
2012/06/19(火) 22:13:50.40でも最初にそういう条件なかったよね。
0118名無しさん@お腹いっぱい。
2012/06/20(水) 11:35:27.52その先の創意工夫は自分でやるんだよ
なんでもおんぶにだっこじゃ教育によくない
0119名無しさん@お腹いっぱい。
2012/06/20(水) 14:14:27.58最初の一行目に世界のどこか、例えばって書いてあるのになにいってんの?
0120名無しさん@お腹いっぱい。
2012/06/20(水) 14:28:46.20お題を整理しよう。
環境変数TZがすでに設定されている(日本時間とは限らない)場合も含めて、
GNU dateを使わずに、dateで1日前の日付(時刻)を取得する方法は?
というのが元のお題。
0121名無しさん@お腹いっぱい。
2012/06/20(水) 14:37:08.98ん?
どういうこと?
0122名無しさん@お腹いっぱい。
2012/06/20(水) 14:40:02.24GNU date ない環境では perl でワンライナー書いてたな。
perl すらない環境には当たったことがなかった。
0123名無しさん@お腹いっぱい。
2012/06/20(水) 14:40:54.150124名無しさん@お腹いっぱい。
2012/06/20(水) 14:43:50.35なるべく汎用性が高い方法で、ってことじゃないなあ。
0125名無しさん@お腹いっぱい。
2012/06/20(水) 14:45:03.99○じゃないかな
0126名無しさん@お腹いっぱい。
2012/06/20(水) 14:56:47.76>>99で出てるな。
0127名無しさん@お腹いっぱい。
2012/06/20(水) 15:04:20.810128名無しさん@お腹いっぱい。
2012/06/20(水) 15:06:30.87perlといってもうちの環境じゃコアモジュールすら無いけどな
何をやるにも車輪作り直しだから楽しいといえば楽しい
0129名無しさん@お腹いっぱい。
2012/06/20(水) 15:11:35.40そういう環境では>>120はどうやるの?
0130名無しさん@お腹いっぱい。
2012/06/20(水) 15:22:57.02諦めてた
0131名無しさん@お腹いっぱい。
2012/06/20(水) 15:24:14.500132名無しさん@お腹いっぱい。
2012/06/20(水) 16:40:08.45標準関数はだいたいある
昨日の日付くらいなら自力でなんとかなるよ
0133名無しさん@お腹いっぱい。
2012/06/24(日) 21:01:25.05その結果をスクリプト内の変数に入れるにはどうすればいいのん?
コマンド発行まではググってすぐにわかったんだけど結果取得がよくわかんない(´・ω・`)
0134名無しさん@お腹いっぱい。
2012/06/24(日) 21:07:37.570135名無しさん@お腹いっぱい。
2012/06/24(日) 21:54:23.75その接続先でコマンドを発行して結果を取得したいのです…
0136名無しさん@お腹いっぱい。
2012/06/24(日) 22:09:29.980137名無しさん@お腹いっぱい。
2012/06/24(日) 22:10:23.28そういうことなら ssh 使う方が楽じゃない?
0138名無しさん@お腹いっぱい。
2012/06/24(日) 22:12:20.950139名無しさん@お腹いっぱい。
2012/06/24(日) 23:24:18.51前回の expect から今回の expect までの文字列すべてが $expect_out(buffer) に
格納されるから、それを処理すればよい。
以下は /var/log/wtmp のファイルサイズを取得する例。
send -- "ls -al /var/log | egrep -e \"\[ \]wtmp$\"\r"
set bprompt 0
while { $bprompt < 1 } {
expect {
# わざと "\r\n" で expect 掛けて、1行1行ぶつ切りにしてプロンプト手前の1行だけ回収。
-re "\r\n" { set last_line $expect_out(buffer) }
-re ".*\[\$\] " { set bprompt 1 }
}
}
# 正規表現で ls の5カラム目だけ $fsize に切り出し。
if { [ regexp {^\S+\s+\S+\s+\S+\s+\S+\s+(\S+)\s} $last_line i_all fsize ] } {
send -- "export WTMPSIZE=$fsize\r"
}
0140名無しさん@お腹いっぱい。
2012/06/24(日) 23:44:45.76出力行数をコマンド側で極力減らしておく、ということを言いたかったのですが
例としては不適切でした。
0142名無しさん@お腹いっぱい。
2012/06/26(火) 09:23:23.94expect -c "
spawn telnet 127.0.0.1
expect \"$ \"
send \"ls\r\"
expect eof
"
こんな風に書いてて
「よーしとりあえずexpectの外でecho $expect_out(buffer)を入れてlsの結果を表示するぞー」
とか思ってたらなんかどこに入れるかわからんかった
というより、expectの使い方がわかってない気がした…
0143名無しさん@お腹いっぱい。
2012/06/26(火) 11:39:01.09鍵設定して
OUT=`ssh hoge@127.0.0.1 ls`
とかでいいじゃん。
0144名無しさん@お腹いっぱい。
2012/06/26(火) 12:03:19.34端からexpectありき、で考えること自体が間違っているわな。
0145名無しさん@お腹いっぱい。
2012/06/26(火) 15:29:34.230146ワラ
2012/06/26(火) 15:57:31.38シェルスクリプトは全部こっちで動かすとして、
#! /usr/bin/expect -f
spawn telnet ホスト名
expect "login:\ "
send "ログイン名\r"
expect "assword:"
send "パスワード\r"
expect "^ホゲ$ "
send "ls¥r"
expect "^ホゲ$ "
send "exit\r"
を下請けコマンドにしてやってみれ。(プロンプトは"ホゲ$ "と仮定)
0147名無しさん@お腹いっぱい。
2012/06/26(火) 16:08:59.940148133
2012/06/26(火) 16:18:50.38動かす方は全てクライアント側です
早速そのスクリプトをe.shで保存
expect e.shとして接続を確認
呼び出し側のスクリプトclient.shで
#!/usr/bin/env bash
OUT=`expect e.sh`
echo $OUT
とするとConnection closed by foreign host.oel Chiappa.c. Reserved.というエラーが…
むむむ…
0149名無しさん@お腹いっぱい。
2012/06/26(火) 16:21:53.21ならそれを先に言えよ。
そもそもls使えんのか?
0150133
2012/06/26(火) 16:25:27.80シリアル接続のルータです
lsは仮で使用出来るコマンドを発行してます
でもexpect -f e.sh や expect e.shだとOKなんですが
シェルスクリプト内でやると駄目だよーと怒られるんです(´・ω・`)
0151名無しさん@お腹いっぱい。
2012/06/26(火) 16:27:25.920152名無しさん@お腹いっぱい。
2012/06/26(火) 16:27:40.89○シリアル接続が出来るルータ
0153名無しさん@お腹いっぱい。
2012/06/26(火) 16:28:08.540155名無しさん@お腹いっぱい。
2012/06/26(火) 16:29:27.55だからperl何かをみんな使う。
0156名無しさん@お腹いっぱい。
2012/06/26(火) 16:29:29.22それエラーじゃないでしょ。
向こう側が接続を切った、って言ってるだけ。
0157133
2012/06/26(火) 16:33:03.55そうなんだ…
>>156
expect e.shだと出来るんですよね
でもシェルスクリプト内で呼び出すと先ほどのエラーがでちゃう
うーむ…
0158名無しさん@お腹いっぱい。
2012/06/26(火) 16:40:34.41標準出力が端末以外の状態だとダメなんだろ。
expect e.sh だとOKでも、
expect e.sh | cat ではNGとか。
だったら OUT=`expect e.sh` も NGになる。
0159133
2012/06/26(火) 16:44:09.27いえ、expect e.sh | catと打ち込んでも出来ました
でもシェルスクリプト内で>>148のようにするとエラーが返って来ちゃうんです
0160名無しさん@お腹いっぱい。
2012/06/26(火) 16:48:13.20シェルスクリプトの「外」で、
OUT=`expect e.sh`
echo "$OUT"
って打ち込むとどうなる?
0161ワラ
2012/06/26(火) 16:49:51.330163名無しさん@お腹いっぱい。
2012/06/26(火) 16:53:23.12じゃあ、
expect e.sh > OUT
cat OUT
で妥協。
0164133
2012/06/26(火) 16:57:30.29ばっちり出来ますた!
ちなみに別ファイルを用意せずにシェルスクリプト内でexpect -c ""みたいにする事は出来ないのかな?
出来ないから別ファイル用意してexpectやperlを使用するようにと言われてるような気もするけど…
0165ワラ
2012/06/26(火) 17:02:26.40たぶんあんたが色々勘違いしてるだけ。
ルータの連続ログイン禁止に抵触してたり。
エラー処理がない>>146もどうかと思うけど。
0166名無しさん@お腹いっぱい。
2012/06/26(火) 17:04:50.56連続ログイン?
そういったルールによるアクセス制御はありませんよ
ちなみにexpect -cだと具体的に>>146はどう書くんです?
0167名無しさん@お腹いっぱい。
2012/06/26(火) 17:09:57.500168名無しさん@お腹いっぱい。
2012/06/26(火) 17:26:29.45シングルクオートでくくって、¥等をエスケープするだけ。
0169名無しさん@お腹いっぱい。
2012/06/26(火) 18:57:55.22expect -c "
spawn telnet ${HOST}
expect \"login: \"
send \"${USER}\r\"
expect \"assword: \"
send \"${PASS}\r\"
expect \"$\"
" > OUT
cat OUT
でもこうやって全出力を他のファイルに落としてゴニョゴニョするより(ry
0170名無しさん@お腹いっぱい。
2012/06/26(火) 19:08:18.81コマンド > OUT
cat OUT
なら動作するのに、
OUT=`コマンド`
echo "$OUT"
では動作しないのって、どういうケースが考えられる?
0171名無しさん@お腹いっぱい。
2012/06/26(火) 19:32:35.020172名無しさん@お腹いっぱい。
2012/06/26(火) 19:39:47.98そういう話はしてないだろ
0173名無しさん@お腹いっぱい。
2012/06/27(水) 20:34:48.42普通はどうやるものなのでしょうか?
例えば左シフトする演算をやるとすると、固定幅でない場合は面倒です。
計算後に一々固定幅に除算するのは速度的にどうかと思うし、
皆さんがどのような手段をとっているのか、おすすめの方法を教えて下さい。
0174名無しさん@お腹いっぱい。
2012/06/27(水) 20:35:48.090175名無しさん@お腹いっぱい。
2012/06/27(水) 20:56:11.44bashなら64bit(符号付)で固定幅だよ。
左シフトしてオーバーフローしたビットは自動的にカットされる。
$ echo $((0x7fffffffffffffff))
9223372036854775807
$ echo $((0x7fffffffffffffff<<1))
-2
$ echo $((0x7fffffffffffffff<<2))
-4
0176名無しさん@お腹いっぱい。
2012/06/27(水) 21:28:12.131.
bashが64bit幅(符号付)というのは、bashの仕様でしょうか?
それとも、事実上、それが基本になっている事が多いということでしょうか?
2.
32bit幅の固定幅bit演算、符号なしの論理演算をする時は、
やはり %0xFFFFFFFF 等と、演算を行った後に
適宜修正して計算するのが普通なのでしょうか?
0177名無しさん@お腹いっぱい。
2012/06/27(水) 23:10:24.880178名無しさん@お腹いっぱい。
2012/06/27(水) 23:11:20.590179名無しさん@お腹いっぱい。
2012/06/28(木) 07:54:55.060180名無しさん@お腹いっぱい。
2012/06/28(木) 10:56:16.200181名無しさん@お腹いっぱい。
2012/06/28(木) 10:59:29.130182名無しさん@お腹いっぱい。
2012/06/28(木) 11:03:12.480183名無しさん@お腹いっぱい。
2012/06/28(木) 11:27:39.660184名無しさん@お腹いっぱい。
2012/06/28(木) 11:28:26.830185名無しさん@お腹いっぱい。
2012/06/28(木) 13:34:47.48流れを読んでいないけど、
男なら黙ってmanだろ。
$ man -k loopback
lo(4) - software loopback network interface
0186名無しさん@お腹いっぱい。
2012/06/28(木) 13:37:43.27loopback: nothing appropriate.
$ man loopback
No manual entry for loopback
0187名無しさん@お腹いっぱい。
2012/06/28(木) 13:55:49.47シェルスクリプトとは別の話じゃないのか。
0188名無しさん@お腹いっぱい。
2012/06/28(木) 14:17:25.200189名無しさん@お腹いっぱい。
2012/06/28(木) 18:04:41.350190名無しさん@お腹いっぱい。
2012/06/28(木) 18:07:40.500191名無しさん@お腹いっぱい。
2012/06/29(金) 17:10:34.14それをコマンド引数に渡すってことをやってたんだけど
$ options="+profile '*'"
$ convert $options image1.jpg image2.jpg
bash 4.2でパラメータ中に*や'があると展開時にエスケープされるようになった
$ set -x
$ convert $options image1.jpg image2.jpg
+ convert +profile ''\''*'\''' image1.jpg image2.jpg
結局Arrayを使うことにしたんだけど
$ options=(+profile '*')
$ convert "${options[@]}" image1.jpg image2.jpg
これってbashのバグなんだろうか?それともANSIの仕様?
bashに特殊文字のエスケープやめさせる方法無いんだろうか?
こんなふうに複数のパラメーターを一気に渡そうって発想が横着なのかもしれないけど
だったらArray使わない移植性あって手軽な方法って無いのかな?
$ convert $(echo $options)
は思いついたけどなんか嫌だし、副作用もあるので
0192名無しさん@お腹いっぱい。
2012/06/30(土) 03:45:58.31$ ls
1.jpg 2.jpg
$ o="+p *"
$ echo $o
+p 1.jpg 2.jpg
$ echo "$o"
+p *
$ o="+p '*'"
$ echo $o
+p '*'
$ echo "$o"
+p '*'
$ bash --version
GNU bash, バージョン 4.2.10(1)-release (i686-pc-linux-gnu)
...
■ このスレッドは過去ログ倉庫に格納されています