トップページunix
985コメント289KB

シェルスクリプト総合 その8

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2007/02/15(木) 14:28:44
シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>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 でトレースしましょう。

前スレ
シェルスクリプト総合 その7
http://pc10.2ch.net/test/read.cgi/unix/1157601611/
0381名無しさん@お腹いっぱい。2007/04/25(水) 22:06:43
「試験に出るシェルスクリプト」
0382名無しさん@お腹いっぱい。2007/04/26(木) 00:34:12
>>381
その筋質問箱は付いてますか?
0383名無しさん@お腹いっぱい。2007/04/26(木) 04:36:49
Z80は最強だから大丈夫
0384名無しさん@お腹いっぱい。2007/04/26(木) 10:22:57
じゃあ「できるシゥルスクリプト」
0385名無しさん@お腹いっぱい。2007/05/02(水) 17:38:53
英小文字からなる文字列の最初の一文字だけを大文字に変換するには
どうすればよいのでしょうか?

sedだと只それだけで一文字目の後ろに改行を挿入してホールドスペースに入れて、
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/ てなことして
また連結して改行を削除みたいな、バカ手間が掛かるので投げ出してしまった。
もっと簡潔に出来たら良いなと思うのですが・・・
0386名無しさん@お腹いっぱい。2007/05/02(水) 17:42:25
>>385
echo aaa | sed 's/\(.\)/\U\1/'
03873852007/05/02(水) 18:01:30
>>386

それは。どこのsedですか?
うちではそれはUaaaと出力します。\Uという正規表現はUそのものを表すようです。
03883852007/05/02(水) 18:42:47
ちょっと調べてみたらGNUのsedだと、>>385の動作が出来るようです。
しかし、なんでもコマンドを高機能なやつに入れ替えるのもどうかと思うし、
使っているOSがGNUツール群を標準装備していないのもそれなりに理由があるだろうし
高々文字列変換で新たなツールを使うのには、消極的になりますね。
0389名無しさん@お腹いっぱい。2007/05/02(水) 19:11:07
echo "abc" | awk '{print toupper(substr($0,1,1))substr($0,2)}'
echo "abc" | perl -pe 's/(.)/\U\1/'
0390名無しさん@お腹いっぱい。2007/05/02(水) 19:18:21
echo aaa | awk -v FS= -v OFS= '{$1=toupper($1);print}' はどう。
03913852007/05/02(水) 20:06:42
>>389
有り難うございます。
awkのsubstrで文字位置指定して、toupperで大文字に変換ということですね。
perlの方はgsedと互換な感じの構文ですね。(てかgsedが模倣した?)
>>390
済みません。
awk: illegal statement
input record number 1, file
source line number 1
と成ります。

いずれにしてもいろいろと勉強になります。
>>386,>>389,>>390の皆さん、ありがとうございました!
0392名無しさん@お腹いっぱい。2007/05/03(木) 02:41:58
GNU の sed でも y/a-z/A-Z/ みたいな表現できないんだよね。
互換性維持のためなんだろうけど。
0393名無しさん@お腹いっぱい。2007/05/03(木) 09:18:45
kshのコマンドヒストリで矢印キーが使いたいのだが、
emacsのCTRLキーはめんどい。
エロい人、設定のしかた教えてチョ。
0394名無しさん@お腹いっぱい。2007/05/03(木) 10:08:20
>>393
くだらない質問はここに書き込め!Part 52
http://pc11.2ch.net/test/read.cgi/unix/1176049968/
0395名無しさん@お腹いっぱい。2007/05/03(木) 18:24:22
>>393
bashつかえw
0396名無しさん@お腹いっぱい。2007/05/04(金) 16:26:20
cshで変数の中に空白文字で区切られた複数のワードからなる文字列が代入されてる。
例:「aaa bbb ccc ...」
各ワードに接頭辞と接尾辞を付加したいが、sedでできるかな?
例:「prefix.aaa.postfix prefix.bbb.postfix prefix.ccc.postfix ...」
ちなみにワード数は不定。
置換後の文字列長はLINE_MAX以下でないと駄目?

0397名無しさん@お腹いっぱい。2007/05/04(金) 16:44:54
はい、cshはスルー、次の方どうぞ
0398名無しさん@お腹いっぱい。2007/05/04(金) 16:56:59
こんなんでよい? bashだけど

$ s="aaa bbb ccc"
$ echo $s | sed -e 's/\([^ ]*\)/prefix.\1.postfix/g'
prefix.aaa.postfix prefix.bbb.postfix prefix.ccc.postfix

0399名無しさん@お腹いっぱい。2007/05/04(金) 23:17:48
Gnomeなどのデスクトップ環境でxxx.shに何らかのファイルをドロップしたとすると、そのファイル名はどういった変数に格納されているのでしょうか。
tex処理を簡単にしたいと考えたのですが、これが分からずにつまっています。
0400名無しさん@お腹いっぱい。2007/05/05(土) 00:39:09
$1, $2, ...
0401名無しさん@お腹いっぱい。2007/05/05(土) 06:17:46
>>398
$1,$2...って9個までしか使えないんじゃ?
396は「ワード数不定」って言ってるから、10個以上もありうるだろ。

0402名無しさん@お腹いっぱい。2007/05/05(土) 06:21:09
↑gオプション付いてるやん。何かみついてんだコイツ
0403名無しさん@お腹いっぱい。2007/05/05(土) 14:01:50
>>401
アホー

>>400>>399へのレスだ。
0404名無しさん@お腹いっぱい。2007/05/05(土) 23:04:16
>>399
多分、コマンドでこう起動したのと同じ扱いになっている思う。

$ xxx.sh < "abc.tex"

スクリプト側でリダイレクトされる前のファイル名を
取得する方法が分かれば、どうにかなるんじゃないかな。
0405名無しさん@お腹いっぱい。2007/05/06(日) 01:12:45
画像変換するスクリプトを作っています。
スクリプ中で使用するコマンド(今回はmogrify)がインストールされているかどうか
調べるのに手っ取り早い方法ありますか?

今のところ思いつくのは、PATHから「:」で区切って1つづつ抜き出し、その直下に
mogrifyがあるか「test -x」する方法です。
04064052007/05/06(日) 01:26:07
ちょっと自己解決

whereis使えばいいか。
whereisって見つからなくても0返すんですね・・・

whereis -b mogrifya | grep -v ':$' > /dev/null
if [ $? ...
って感じかな

もっとスマートな方法ありましたらご教授ください。
0407名無しさん@お腹いっぱい。2007/05/06(日) 01:47:14
whichは?
0408名無しさん@お腹いっぱい。2007/05/06(日) 02:09:28
if which mogrify > /dev/null 2>&1 ; then
...
は?
0409名無しさん@お腹いっぱい。2007/05/06(日) 02:18:36
>407,408
whichか、なるほど
解決しましたありがとうございました。
04104052007/05/06(日) 02:45:19
たびたびすいません
&&や||の後に複数のコマンドを書くにはどうすればいいのでしょうか?

見つからなかった場合、NGと表示しexitしたいのですが、
which mogrify > /dev/null 2>&1 && echo 'bc ok' || (echo 'bc NG'; exit 1)
としてもミニシェルから抜けるだけなのです

if文で書けばいいだけなのですが、勉強の意味でも知っておきたいのです。
0411名無しさん@お腹いっぱい。2007/05/06(日) 03:18:41
function echo_exit() {
echo $*
exit
}
とか定義しちゃえば?
0412名無しさん@お腹いっぱい。2007/05/06(日) 03:28:54
>>410
... || { echo NG; exit 1; }
は?
04134102007/05/06(日) 11:45:38
>411
いいですね。たくさんコマンド実行したいときに使わせていただきます。

>412
おー、意図したとおりになりました。今回はこちらを使わせていただきます。

ありがとうございました。


ちなみにcommand1が成功したときはcommand2、失敗したときはcommand3という時に、
command1 && command2 || command3
という書き方は問題ないですか?
動作は意図したとおりなんだけど、「|| command3」はcommand2の結果に
かかってくるように見えるのでちょっと気持ち悪い・・・
0414名無しさん@お腹いっぱい。2007/05/06(日) 12:35:35
>>413
>command1 && command2 || command3
>という書き方は問題ないですか?

command2が falseを返した時、command3まで実行されてしまうのが問題。
if - else の代わりにするなら、

command1 && { command2; true; } || { command3; }

と書けば完全。command2や command3は、; で区切って複数コマンド可能。
04154132007/05/06(日) 14:40:39
>414
なるほど。
command2にはechoとかしか入れてなかったので気づかなかった・・・
勉強になりました。ありがとうございます。
0416名無しさん@お腹いっぱい。2007/05/11(金) 23:38:51
tail -f ログファイル名 | awk -f 手続きファイル

上記コマンドを指定の条件をつけてwhileによる繰り返しでログを整形する
シェルをつくりたいのですが、末尾に">>ファイル名"としても指定のファイル
にリダイレクトできません。
while〜doneの後、シェルスクリプト実行時の末尾に>>を指定してもだめです。
出力は画面のままです。(通常のtail -fのイメージ)
&でバックグラウンドで実行しても同様です。

tail -f で読み取っている内容を別のログファイルに出力するにはどうすれば
よいですか?
0417名無しさん@お腹いっぱい。2007/05/12(土) 09:13:18
teeじゃだめ?
0418名無しさん@お腹いっぱい。2007/05/12(土) 10:06:11
シェルってゆーな。クズ。
0419名無しさん@お腹いっぱい。2007/05/14(月) 21:13:31
tail -f って終了しないじゃん
0420名無しさん@お腹いっぱい。2007/05/15(火) 00:34:17
tee -a hoge.log
0421名無しさん@お腹いっぱい。2007/05/15(火) 17:57:30
hoge%68%6F%67%65 のような文字列を
%68%6F%67%65%68%6F%67%65 のように
%表記に直すにはどうしたらよいでしょうか?
0422名無しさん@お腹いっぱい。2007/05/15(火) 18:50:16
perlつかえ。
0423名無しさん@お腹いっぱい。2007/05/15(火) 18:50:23
>>421
よく意味がわからんが、URLエンコーディングとかの話か?
0424名無しさん@お腹いっぱい。2007/05/15(火) 19:05:07
>>423
よく意味がわからんなら答えなくていいよ。
0425名無しさん@お腹いっぱい。2007/05/15(火) 19:25:20
>>421
s/hoge%68%6F%67%65/%68%6F%67%65%68%6F%67%65/g
0426名無しさん@お腹いっぱい。2007/05/15(火) 19:27:18
>>425
できました!! ありがとう!!
0427名無しさん@お腹いっぱい。2007/05/15(火) 19:28:00
自演乙
0428名無しさん@お腹いっぱい。2007/05/16(水) 01:53:36
ESP発揮して混じれ酢すると
hogeを%表記しようとしたときに
右側の既に%表記されてる部分が
さらに%表記に変換されてしまうことを
回避したいと思っているのではないかと
0429名無しさん@お腹いっぱい。2007/05/16(水) 02:00:50
一旦デコードしてからエンコードするのが確実だな
04302012007/05/16(水) 02:03:24
01.jpg 02.jpg 03.jpg 04.jpg ...

と沢山のファイルがあってfor文(じゃなくてもいいけど)により

convert +append 01.jpg 02.jpg 03.jpg out1.jpg
convert +append 04.jpg 05.jpg 06.jpg out2.jpg
...

というように、3つずつ抜き出して一気に処理したいのですが、どうすればいいのでしょうか?
0431名無しさん@お腹いっぱい。2007/05/16(水) 02:23:41
>>430
100個ずつとかだと別の方法を使うが、3個ずつならこんなもんか

#!/bin/sh
set -- ??.jpg
i=1
while :; do
case $# in
0) break;;
1) convert +append $1 out$i.jpg; break;;
2) convert +append $1 $2 out$i.jpg; break;;
*) convert +append $1 $2 $3 out$i.jpg; shift; shift; shift; i=`expr $i + 1`;;
esac
done
0432名無しさん@お腹いっぱい。2007/05/16(水) 02:27:07
set -- *.jpg
i=0
while [ $# -gt 0 ]; do
i=`expr i + 1` #式使えるならそれでも。
convert +append $1 $2 $3 out$i.jpg
shift 3
done

shiftの数引数ってBourne Shellでも使えるのかな。
使えないなら3回shift。
0433名無しさん@お腹いっぱい。2007/05/16(水) 02:27:49
ああ、ちょうど3の倍数になっていない場合は考慮してなかったな。
0434名無しさん@お腹いっぱい。2007/05/16(水) 02:28:55
ちょうど3の倍数になっていない場合はどうすんの?
0435名無しさん@お腹いっぱい。2007/05/16(水) 02:29:55
/dev/null とかで補完
0436名無しさん@お腹いっぱい。2007/05/16(水) 02:37:35
名前欄は無視でお願い
04374302007/05/16(水) 02:45:01
おお、夜食食べている間にこんなにもレスが
3の倍数になっていないときは私自身考慮してませんでいした。
431さんの set だけ使ったことがないのですが、とにかく
>431-435 で十分対処できそうです。
setも調べてみます
ホントにありがとうございます。





04384302007/05/16(水) 02:46:51
よく見たら432さんもsetありましたね。
とにかくありがとう
04394212007/05/16(水) 11:12:47
>>422
シェルスクリプトで難しいならperlを使ってもかまいません。

>>423
URLエンコーディングならアルファベットはそのままだと思うのですが、
アルファベットも16進数表示したいわけです。
pukiwiki のバックアップをローカルに落とすのに、
ファイル名を知りたいんです。
0440名無しさん@お腹いっぱい。2007/05/16(水) 11:21:18
>>439
pukiwikiスレあたりで「戻し方教えれ」って聞いた方がいいんじゃね?
04414162007/05/16(水) 23:44:33
ご返事いただきありがとうございます。

tail -f ログファイル名 | awk -f 手続きファイル

上記コマンドではawkによる整形結果を標準出力できる状態で、
さらにパイプでteeコマンドを実行してみましたがうまくログが
出力できませんでした。

名前付きパイプを作成し、オリジナルログの出力先を名前つきパイプにして
直接awkで名前つきパイプを標準入力状態にしても、tail -f のような画面に
標準出力はできますがファイルへのリダイレクトは無理でした。
難しいですねぇ。。
0442名無しさん@お腹いっぱい。2007/05/17(木) 00:48:16
tee の使い方間違ってるだけだろ
0443ウサチャソ2007/05/17(木) 00:52:02
>>441
tail -f をパイプすると、上手く動かないよ。
GNUのだとどうなんだろ?

「tail パイプ バッファリング」
でググると、それっぽい事いっぱいでてくるYO
0444名無しさん@お腹いっぱい。2007/05/17(木) 18:41:18
a.shに . b.sh として読み込まれるb.shが自分の名前がb.shであると知る方法はありますか?
0445名無しさん@お腹いっぱい。2007/05/17(木) 18:50:24
>>444
ない。
. で読む場合は $0もセットされないし。
0446名無しさん@お腹いっぱい。2007/05/17(木) 19:05:57
>>445
ありがとうございます。
あらかじめ埋め込んでおくしかなさそうですね…。
04474162007/05/17(木) 23:00:53
>>443
バッファの問題だったんですね。

通常のawkはやめて、gawkのfflush関数を使うことでうまくいきました。
ありがとうございました。
0448名無しさん@お腹いっぱい。2007/05/18(金) 19:10:57
シェルスクリプトでログインログアウトを自動化するにはどうしたらいいでしょうか?
もし良かったら数行のコマンドでレスお願いします。
0449名無しさん@お腹いっぱい。2007/05/18(金) 19:15:55
>>448
何をやりたいのかもうちょい詳しく。
04504482007/05/18(金) 19:59:20
>>449

1.現在rootでログイン中。
2.testユーザーでログインして何か作業をする。
3.そしてまたrootに戻る。

これを自動化したいです。
0451名無しさん@お腹いっぱい。2007/05/18(金) 20:03:21
>>450
su test 何か
もしくは
su - test 何か

違いについては man su 等を参照。
0452名無しさん@お腹いっぱい。2007/05/18(金) 20:30:15
>>451
間違ってるよ。man su 等を参照するべきなのはオマエ。
0453名無しさん@お腹いっぱい。2007/05/18(金) 20:59:46
>>450
sudoじゃダメなんか?
0454名無しさん@お腹いっぱい。2007/05/18(金) 21:30:20
>>448
testユーザで実行するバッチファイルを作っておいて、
  su - test -c バッチファイル
で実行しる。
0455名無しさん@お腹いっぱい。2007/05/18(金) 21:35:19
バッチファイル
バッチファイル
バッチファイル
バッチファイル
wwww
0456名無しさん@お腹いっぱい。2007/05/19(土) 00:37:47
ほんとうにloginしたいならexpectを使うとか
04574482007/05/19(土) 03:04:26
rootでログイン中
expectでsu - testとして
touch /home/test.txtを実行して
再度expectでsu - rootでrootになっても
/home/test.txtは作成されてませんでした
なぜでしょう?
0458名無しさん@お腹いっぱい。2007/05/19(土) 10:21:42
パーミッションじゃないの?
/homeにtestユーザは書き込めないんでは。
0459名無しさん@お腹いっぱい。2007/05/20(日) 04:33:32
質問。
11.22.33を
33.22.11に文字を反転させたい。
04604592007/05/20(日) 04:42:15
459は取り消し!
11.22.33を
a[0]=11
a[1]=22
a[2]=33
のように配列に代入したい。
よろしくお願いします。
0461名無しさん@お腹いっぱい。2007/05/20(日) 05:39:47
宿題でつか
04624592007/05/20(日) 06:19:25
宿題でつ
04634592007/05/20(日) 07:14:05
スレ汚してごめんなさいできまつた
0464名無しさん@お腹いっぱい。2007/05/20(日) 21:56:12
テキストファイルに、ファイルの場所がずらずら書かれていて

-----
/usr/local/etc/pussy001.jpg
/usr/local/etc/pussy002.jpg
/usr/local/etc/pussy003.jpg
     :
-----

そこに書かれているファイルを指定した場所に移動させたいんです。
で、こんな感じで動くスクリプトを書きたいなぁと考えているんですが

cat list.txt | grep jpg | mv.sh /work/pussy

この mv.sh の書き方が分かりません。

0465名無しさん@お腹いっぱい。2007/05/20(日) 22:02:27
>>464
mv `grep jpg list.txt` /work/pussy

で、一発。・・・で、pussyってww
0466名無しさん@お腹いっぱい。2007/05/20(日) 22:47:23
>465
残念ながら、ファイル名にスペースがあるとだめでした。
sh, tcsh, bashで試してみましたが、どれも同じです。
0467名無しさん@お腹いっぱい。2007/05/20(日) 23:18:02
>>464 の例では、ファイル名にスペースが入ってないじゃないか。
そういう条件は先に例に含めて書くこと。
ファイル名にスペースがある場合のやり方ももちろん知ってるが、
わざわざ教える気にならないので俺はパス。
0468名無しさん@お腹いっぱい。2007/05/20(日) 23:25:45
>>466
IFS='
' mv `grep jpg list.txt` /work/pussy
0469名無しさん@お腹いっぱい。2007/05/21(月) 00:42:01
(while read f; do mv "$f" dest/ ; done) < file

>>467
ファイルの長さを考慮しないgrep戦法しか提示しなかった奴が
そんな理屈をこねても見苦しいだけ。
0470名無しさん@お腹いっぱい。2007/05/21(月) 06:22:05
>>469
残念ながら、ファイル名に \ があるとだめでした。
0471名無しさん@お腹いっぱい。2007/05/21(月) 10:38:53
じゃあ諦めな。
0472名無しさん@お腹いっぱい。2007/05/21(月) 11:09:30
>>471
ファイル名の \ を考慮しないを考慮しないwhile read戦法しか提示しなかった奴が
そんな理屈をこねても見苦しいだけ。
0473名無しさん@お腹いっぱい。2007/05/21(月) 11:17:06
というか、>>469 って、元の質問の jpg で grepするの忘れてるじゃん。
テストだったら0点。
0474名無しさん@お腹いっぱい。2007/05/21(月) 11:25:38
でもテストじゃないよ。
0475名無しさん@お腹いっぱい。2007/05/21(月) 11:33:37
そういう香具師が、「それはケアレスミス。答えはわかってた」とか後で言うんだよな。
0476名無しさん@お腹いっぱい。2007/05/21(月) 11:37:45
なんでそんな完璧にこだわるんだろ。
質問者のヒントになればいいじゃん。
0477名無しさん@お腹いっぱい。2007/05/21(月) 16:16:07
低能同士、仲良く!
04784642007/05/22(火) 00:44:46
すみません、御礼が遅れました。
という訳で >465 >468 >469 全て参考になりました。特にIFS=〜は初めて
知ったので成程と関心しました。
この場をお借りして厚く御礼申し上げます。
0479名無しさん@お腹いっぱい。2007/05/22(火) 00:59:36
xargsは?

grep jpg list.txt | xargs -i mv {} /work/pussy
0480名無しさん@お腹いっぱい。2007/05/22(火) 12:09:35
>>479
空白が含まれているとダメだろ。
0481名無しさん@お腹いっぱい。2007/05/22(火) 14:28:33
grep jpg list.txt | tr '\n' '\0' | xargs -0 -i mv {} /work/pussy
■ このスレッドは過去ログ倉庫に格納されています