シェルスクリプト総合 その6
■ このスレッドは過去ログ倉庫に格納されています
0001うはwwwww
2006/03/26(日) 00:56:22スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>1-6くらい)をご覧ください。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
Linuxユーザは/bin/shの正体がbashなので特に注意。
・csh/tcshのシェルスクリプトは推奨されません。
(理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
manや参考リンクを見ましょう。
aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
0702名無しさん@お腹いっぱい。
2006/07/08(土) 15:15:05touch $i
end
とか
for i in 1 2 3 4 5 6 7 8 9;do
touch $
done
みたいな感じで、ファイルを名前を問わず
沢山作るにはどうすれば良いのでしょうか?
0703名無しさん@お腹いっぱい。
2006/07/08(土) 15:36:000704名無しさん@お腹いっぱい。
2006/07/08(土) 15:39:480705名無しさん@お腹いっぱい。
2006/07/08(土) 15:40:30sh: seq: command not found
0706名無しさん@お腹いっぱい。
2006/07/08(土) 16:54:270707名無しさん@お腹いっぱい。
2006/07/08(土) 17:55:570708名無しさん@お腹いっぱい。
2006/07/09(日) 02:42:09yes '' | head -10000 | cat -nでなんとかなるが
0709名無しさん@お腹いっぱい。
2006/07/09(日) 10:49:200710名無しさん@お腹いっぱい。
2006/07/09(日) 11:23:32csh -cf 'repeat 100 echo'
0711名無しさん@お腹いっぱい。
2006/07/09(日) 14:06:00して seq を作る。
# もちろん冗談
0712名無しさん@お腹いっぱい。
2006/07/09(日) 17:28:55zshが入っているだろ。
0713名無しさん@お腹いっぱい。
2006/07/09(日) 18:50:08aaa.txt の中身が
------------------
${vvv}
------------------
という記述のときに
#!/bin/sh
vvv="VVVVV"
cat aaa.txt
とした場合
------------------
${vvv}
------------------
ファイルに書いてある内容がそのまんま表示される、これを
------------------
VVVVV
------------------
としたいのです。
要は↓と同じことをもっと簡単に出来る方法はあるかということなのですが
#!/bin/sh
vvv="VVVVV"
v_sed=`sed \'s/\${vvv}/\'\${vvv}\'/g\' aaa.txt`
## sed 's/${vvv}/'VVVVV'/g' aaa.txt
eval ${v_sed}
0714名無しさん@お腹いっぱい。
2006/07/09(日) 19:27:16変数展開だけをファイルオープン前に済ませたいのか。
難しいね。shを自作しないといけないかも。
0715名無しさん@お腹いっぱい。
2006/07/09(日) 20:01:020716名無しさん@お腹いっぱい。
2006/07/09(日) 23:42:560717名無しさん@お腹いっぱい。
2006/07/10(月) 06:54:080718名無しさん@お腹いっぱい。
2006/07/10(月) 08:11:540719名無しさん@お腹いっぱい。
2006/07/10(月) 08:59:360720713
2006/07/10(月) 09:11:44ありがとうございます
やりたい事が出来ました。
0721名無しさん@お腹いっぱい。
2006/07/10(月) 12:54:40あまりに危険すぎるよ...
0722名無しさん@お腹いっぱい。
2006/07/10(月) 13:07:200723名無しさん@お腹いっぱい。
2006/07/10(月) 22:12:57イメージとしては login 時の Passwd: のような感じです。
以下のようなスクリプトを書きたいのですが、人に説明しながらスクリプトを
実行したい場合、パスワードが見えてしまうのでなんとかしたいです。
(さっと思いついた例なので誤字文法ミスは見逃してください)
#!/bin/sh
echo "user: "; read user
echo "passwd: "; read passwd
expect -c "
expect \"login: \"
send \"$user\r\"
expect \"passwd: \"
send \"$passwd\r\"
"
0724名無しさん@お腹いっぱい。
2006/07/10(月) 22:15:42stty -echo
read passwd
stty echo
0725名無しさん@お腹いっぱい。
2006/07/10(月) 22:41:59無知は損ですね。ものすごく助かりました。
man sttyで-echoの意味を調べたところ、
echo (-echo)
Echo back (do not echo back) every character typed.
ということで、そのままecho backさせないということのようです。
ありがとうございました。
0726名無しさん@お腹いっぱい。
2006/07/11(火) 01:02:22read -s
たぶん bash 専用オプションだが。
0727名無しさん@お腹いっぱい。
2006/07/11(火) 21:59:23デフォルト値を表示させておく事ってできるでしょうか?
例えば
入力しろやゴルァ>hogehoge■
としておいて、
ユーザがhogehogeの部分を編集できるようにしたいのですが。
シェルはshかcshかkshが使えるようです。
0728名無しさん@お腹いっぱい。
2006/07/11(火) 23:02:11使えりゃいいのかな。
0729727
2006/07/11(火) 23:46:111.Cでの開発は無理そうだ
2.多分readlineやlibeditは入っていないし、入れることはできないだろう
ユーザから入力を求める際に、あらかじめ入力バッファ(?)に
文字を入れておくこととかできないのだろうか。
0730名無しさん@お腹いっぱい。
2006/07/11(火) 23:54:17入力しろやゴルァ [hogehoge]>■
これが気に入らないなら頑張ってくれ。
0731727
2006/07/12(水) 06:07:57頑張り方が分からない。
0732名無しさん@お腹いっぱい。
2006/07/12(水) 08:05:53みつからないね。もうCかperlかなんかでそういうコマンド用意する
しかないような気がしてきた。
perlだとこう。
use strict;
use Term::ReadLine;
my($prompt, $preput) = @ARGV;
my $term = Term::ReadLine->new('hoge');
my $s = $term->readline($prompt, $preput);
print $s, "\n";
使い方:
x=`perl readline.pl '入力しろやゴルァ>' 'hogehoge'`
しかしこのスレでperlのような飛び道具を使うのは気が引ける...
0733名無しさん@お腹いっぱい。
2006/07/12(水) 08:32:460734名無しさん@お腹いっぱい。
2006/07/12(水) 09:26:46言語の学習は手間暇かかるんだよね。時間も。できればシェルスクリプトで
済ませたい。
あー、俺がもっと頭良ければ、新しい言語ぐらいすぐに覚えるのに。
0735名無しさん@お腹いっぱい。
2006/07/12(水) 09:32:02おぼえるよりよっぽど頭使うと思う。
0736名無しさん@お腹いっぱい。
2006/07/12(水) 10:32:280737727
2006/07/12(水) 23:10:42dくす
だが、perlは入ってないようだ。
仕方がないから、sttyでrawモードにして、
一文字ずつキー入力を取得して編集できるようにした。shだけで。
お客に言われたとき、早いうちに「出来ねぇ」と言っておけば良かったorz...
0738名無しさん@お腹いっぱい。
2006/07/13(木) 06:30:08ターミナル上からならpwdに繋げてなんとかなるんだけど
nautilusやrox、konquerorから実行するとそうもいかない。
$0は相対バスしか返さないし。
ちょっとしたGUIインストーラみたいのを作ってみたいんだけども
0739名無しさん@お腹いっぱい。
2006/07/13(木) 08:19:27無理。
http://www.nurs.or.jp/~asada/FAQ/UNIX/section4.4.html
0740名無しさん@お腹いっぱい。
2006/07/13(木) 08:34:47どうもです。
結局ps p (PID) |sed 's/.* //g'を中で実行してなんとかしました。
0741名無しさん@お腹いっぱい。
2006/07/13(木) 08:57:14それでも第0引き数いじられたら無理じゃない?
0742名無しさん@お腹いっぱい。
2006/07/13(木) 10:19:23嘘を言わないように。
インタープリターがスクリプトファイルを「オープン」して「リード」する必要があるので
スクリプトファイルのファイル名は必ず渡る。
ファイル名をスクリプトに渡す方法はインタープリター依存。
sh,cshなら$0。相対パスだったらカレントディレクトリを補ってやればよい。
0743名無しさん@お腹いっぱい。
2006/07/13(木) 12:13:100744名無しさん@お腹いっぱい。
2006/07/13(木) 12:17:150745名無しさん@お腹いっぱい。
2006/07/13(木) 20:41:28労多くして易少なかった。
0746名無しさん@お腹いっぱい。
2006/07/13(木) 23:51:56でも、そこにある。
0747名無しさん@お腹いっぱい。
2006/07/14(金) 01:19:29どんな環境で使っても
確実にファイルのmtimeを
英数字のみのフォーマットで取得するには
どうしたらベストでしょうか?
ls よりもそれに適したコマンドってあります?
0748名無しさん@お腹いっぱい。
2006/07/14(金) 01:23:320749名無しさん@お腹いっぱい。
2006/07/14(金) 01:31:50env LC_ALL=C ls
0750名無しさん@お腹いっぱい。
2006/07/14(金) 05:58:37そういうことをするには stat が便利なんだが
ポータビリティーを重視しているみたいだから
locale を固定した ls (>>749) をお勧めしておく。
0751名無しさん@お腹いっぱい。
2006/07/14(金) 07:43:16古いOSだと LC_ALLが使えないのがある。
LANG=C LC_TIME=C の方がよりポータブル。
0752名無しさん@お腹いっぱい。
2006/07/14(金) 09:43:54env - PATH=$PATH ls のほうがポータブル
0753名無しさん@お腹いっぱい。
2006/07/14(金) 09:56:45unset LANG LC_TIME LC_ALL; ls
でいいじゃん。
0754名無しさん@お腹いっぱい。
2006/07/14(金) 10:25:340755名無しさん@お腹いっぱい。
2006/07/14(金) 10:26:45サブシェルも知らんのか。
(unset LANG LC_TIME LC_ALL; ls)
0756名無しさん@お腹いっぱい。
2006/07/14(金) 10:36:15当然知っている。知らなかったのは>>753
0757名無しさん@お腹いっぱい。
2006/07/14(金) 10:41:21当然知ってる割には反応が遅かったな。
>>755 見てから「サブシェル」でググったのかい?
>>753 だってサブシェルは知ってると思われ。
当たり前のことは必要なければ省略するから。
たとえば、unset LANG LC_TIME LC_ALL; ls だけの1行で
シェルスクリプトが終るなら、実行後には影響出ないし。
0758名無しさん@お腹いっぱい。
2006/07/14(金) 10:57:05はいはい、後付の言い訳惨め。
0759名無しさん@お腹いっぱい。
2006/07/14(金) 11:01:11後付の言い訳は >>756 = >>754
0760名無しさん@お腹いっぱい。
2006/07/14(金) 11:10:030761名無しさん@お腹いっぱい。
2006/07/14(金) 11:26:131行シェルスクリプトなら、あとexec付けた方がいい。
↓
unset LANG LC_TIME LC_ALL; exec ls -l
0762名無しさん@お腹いっぱい。
2006/07/14(金) 17:18:12必死だな、落第男。www
0763名無しさん@お腹いっぱい。
2006/07/14(金) 19:16:580764名無しさん@お腹いっぱい。
2006/07/14(金) 19:52:00秒単位がわからないとかいう問題の方が大きいな。
ls -l --full-time や ls -T はポータブルじゃないし。
0765名無しさん@お腹いっぱい。
2006/07/14(金) 20:05:01diff -c /dev/null /path/to/file | sed -n 2p
0766名無しさん@お腹いっぱい。
2006/07/14(金) 20:10:25残念だな。テキストファイルだとそれでいいが、
/path/to/file がバイナリファイルだと、diffが拒否するんだよ。
0767名無しさん@お腹いっぱい。
2006/07/14(金) 20:28:30↓
case `uname -s` in
Linux) ls -l --full-time;;
*BSD) ls -T;;
SunOS) ls -e;;
esac
--full-timeの場合は LANG=ja_JP.eucJPでも関係ないみたい。
0768名無しさん@お腹いっぱい。
2006/07/14(金) 20:32:140769名無しさん@お腹いっぱい。
2006/07/14(金) 20:36:30diff -ca にしても問題が4つある。
(1) diff -a オプション自体がポータブルじゃない
(2) 対象ファイルがディレクトリ自体だと動作しない
(3) 対象ファイルが自分のパーミッションで読めないと動作しない
(4) 対象ファイルの中身を読み出してしまうので atimeが変わってしまう
0770名無しさん@お腹いっぱい。
2006/07/14(金) 21:37:280771名無しさん@お腹いっぱい。
2006/07/19(水) 22:02:53bash で↓こんな関数を作ったのですが、
Cygwin なのでディレクトリ名にスペースが入って
select のところがうまくいかなくなってしまいます。
いい書き方はないでしょうか?
function addbm() {
pwd >> ~/.dirbookmark
}
function bm() {
select dir in `cat ~/.dirbookmark`
do
cd $dir
break
done
}
0772名無しさん@お腹いっぱい。
2006/07/19(水) 22:06:25ダブルクォートしる!
"`cat ~/.dirbookmark`"
bashなら catは省略できて、
↓でも桶。
"`< ~/.dirbookmark`"
0773名無しさん@お腹いっぱい。
2006/07/19(水) 22:09:25ダブルクォートだとファイル中の複数行が全部つながって解釈されるだろ。
↓が正解。IFSのあとにシングルクォートした改行コードね。
IFS='
'
0775名無しさん@お腹いっぱい。
2006/07/21(金) 22:14:31と最近言えなくて少し寂しい。
0776名無しさん@お腹いっぱい。
2006/07/21(金) 22:33:070777名無しさん@お腹いっぱい。
2006/07/21(金) 22:49:322. 出力にはファイル名:行番号がついてほしい
3. ハイフンで始まる引数はすべてgrepに渡される
の条件を満たすスクリプトが欲しいんですが、
簡単に作ることは可能でしょうか?
0778名無しさん@お腹いっぱい。
2006/07/21(金) 23:01:222の、 出力にファイル名:行番号を付ける処理がちょっと面倒だけど、
「可能か?」という質問なら「可能」
0779名無しさん@お腹いっぱい。
2006/07/21(金) 23:25:45テストとかは自分でやってくれ。
#! /bin/sh
while [ $# -gt 0 ] ; do
case "$1" in
-*)
opt="$opt $1"
shift
;;
*)
break
;;
esac
done
nkf -e $* | grep -n -H $opt
0780名無しさん@お腹いっぱい。
2006/07/21(金) 23:32:11-n とか -H を grep につけた意味が無いな。
>>778 の面倒ってそういう事か。
確かにできなくはないけど >>779 に
2、3 行足すくらいじゃ出来そうもないな。
0781名無しさん@お腹いっぱい。
2006/07/21(金) 23:32:51それだと grepが標準入力から読んじゃうから、
ファイル名の表示ができない。
それでいいなら問題ないし、もっと簡単に書ける。
>>778 が言うように、ファイル名:行番号を付ける処理のところが面倒。
0782名無しさん@お腹いっぱい。
2006/07/22(土) 00:11:300783名無しさん@お腹いっぱい。
2006/07/22(土) 00:15:17case "$i" in
-*) arg="$arg $i";;
*) files="$files $i";;
esac
for f in $files; do
nkf -e $f | grep -Hn $args
done
ちゃんと動くかどうかは知らね。
0784名無しさん@お腹いっぱい。
2006/07/22(土) 00:16:360785名無しさん@お腹いっぱい。
2006/07/22(土) 00:20:55- nkf -e $f | grep -Hn $args
+ nkf -e $f | grep -n $arg | sed "s;^;$f:;"
0786名無しさん@お腹いっぱい。
2006/07/22(土) 05:08:000787名無しさん@お腹いっぱい。
2006/07/22(土) 08:14:19内部コマンドの getoptsの方がモアベター。
0788777
2006/07/22(土) 10:04:37↓こんな感じになりました。
これだとまだ
・grep の「-e パターン」という指定方法ができない
・スペースを含むファイル名を正しく扱えない
という問題がありますが。
getopt を使えば解決できますかね?
#!/bin/sh
for i in "$@"; do
case "$i" in
-*) arg="$arg $i";;
*) if [ "$pattern" = "" ]; then
pattern="$i"
else
files="$files $i"
fi
;;
esac
done
#echo "pattern="$pattern
#echo "files="$files
#echo "arg="$arg
for f in $files; do
nkf -e "$f" | grep -n $arg "$pattern" | sed "s;^;$f:;"
done
0789名無しさん@お腹いっぱい。
2006/07/22(土) 14:19:04それだけ愛に飢えているのか?
0790名無しさん@お腹いっぱい。
2006/07/22(土) 15:03:150791名無しさん@お腹いっぱい。
2006/07/22(土) 19:01:410792名無しさん@お腹いっぱい。
2006/07/23(日) 01:12:30季節の話題、今日の暦、今日は何の日
をプレーンテキストで取り出してメールで送るようにしたいんですが
どうすればいいでしょう。
w3mかcurlでページを取得してsedを使って必要な分を取り出してmailで送るのをcronすれば
いいんですよね
0793名無しさん@お腹いっぱい。
2006/07/23(日) 01:26:070794名無しさん@お腹いっぱい。
2006/07/23(日) 09:50:43漏れだったら、perlで全部処理するけどな。LWPモジュール+Socketモジュール+cron
0795名無しさん@お腹いっぱい。
2006/07/23(日) 10:19:060796名無しさん@お腹いっぱい。
2006/07/23(日) 10:46:560797名無しさん@お腹いっぱい。
2006/07/23(日) 12:34:510798名無しさん@お腹いっぱい。
2006/07/23(日) 12:43:070799名無しさん@お腹いっぱい。
2006/07/23(日) 12:47:140800名無しさん@お腹いっぱい。
2006/07/23(日) 12:47:38perlしか知らない厨が不安になって自己弁明するために「俺ならperlでやる」みたいな
カキコするのいいかげんやめれ。
■ このスレッドは過去ログ倉庫に格納されています