トップページunix
1001コメント351KB

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

レス数が900を超えています。1000を超えると表示できなくなるよ。
0001名無しさん@お腹いっぱい。2010/02/20(土) 14:10:05
シェルスクリプトの総合スレです。 
スクリプトのお勉強・自慢・腕試しなどにどうぞ。 
まずは注意点、リンク、地鎮祭など(>>1-6くらい)をご覧ください。 

□お約束 
・特記なき場合は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 でトレースしましょう。 

前スレ 
シェルスクリプト総合 その15
http://pc12.2ch.net/test/read.cgi/unix/1246408968/l50
0837名無しさん@お腹いっぱい。2010/10/02(土) 19:08:25
>>836
わぁ、すみません・・・
仰る通りでした。途中で別の所を呼んでたのをすっかり忘れておりました。
お手数おかけしました・・・
0838名無しさん@お腹いっぱい。2010/10/04(月) 15:12:52
次はLinux板で聞いてね。
0839名無しさん@お腹いっぱい。2010/10/04(月) 16:19:30
>>838
別にLinux依存の質問じゃないし、こっちで聞いていいよ。
あと、Linux板のシェルスクリプトスレは落ちて終了したから、こっちで聞くしかない。
0840名無しさん@お腹いっぱい。2010/10/04(月) 16:43:16
くだ質で聞けばいいんじゃね。
0841名無しさん@お腹いっぱい。2010/10/06(水) 11:17:31
出力をしたくないときによく
./hogehoge >/dev/null 2>&1
とやりますが、なぜリダイレクトは後ろから評価されるのですか?
この順序に例外はありますか?
0842名無しさん@お腹いっぱい。2010/10/06(水) 11:36:15
>>841
後ろから評価されてないよ。

2>&1 は 標準エラーを標準出力と同じところに出力するということ。
./hogehoge >/dev/null 2>&1
の場合は 2>&1 が評価された時点で、標準出力が /dev/null に設定されている
ので、標準エラーも /dev/null に設定される。

./hogehoge 2>&1 >/dev/null
この場合は 2>&1 が評価された時点で、標準出力が画面に表示される設定になっ
ているから、標準エラーが画面表示される。

分かり難い説明だと思うので、検索したほうがいいかも。
0843名無しさん@お腹いっぱい。2010/10/06(水) 11:38:50
後ろからじゃ無くて前からだよ。
1 >/dev/null 標準出力を/dev/nullにリダイレクトする。
2 2>&1 標準エラーを(さっき/dev/nullにリダイレクトした)標準出力にdupする。

感覚に合わないのは、./hogehoge 2>&1 | hagedebu
これは、標準出力をパイプにリダイレクトするのが先。
0844名無しさん@お腹いっぱい。2010/10/06(水) 11:43:35
まぁ dup2 について調べろってことだな
0845名無しさん@お腹いっぱい。2010/10/06(水) 11:46:57
もうちょっとお母さんみたくやさしく
0846名無しさん@お腹いっぱい。2010/10/06(水) 12:06:42
「リダイレクトは後ろから評価される」と、
間違いを堂々と書いてるサイトや文章が結構存在するから注意。

正しくは「前から評価される」
「ファイル記述子の複製」を理解すれば理解できる。
0847名無しさん@お腹いっぱい。2010/10/06(水) 12:19:14
うちの社員研修では「リダイレクトは後ろから評価される」と教えてます。
正しいかどうかよりもわかりやすさ優先なので。
何か問題でも?
0848名無しさん@お腹いっぱい。2010/10/06(水) 13:13:08
>>846
ここでわからないとされるのは、前から評価されるなら
2>&1 で標準エラー出力(2)を標準出力(1)にしたときに
そのあと >/dev/null にしたときに なぜ元標準エラー出力は
釣られないのか というところだろ。
ここを簡潔に説明するのに必要なのはdupの勉強ではない
0849名無しさん@お腹いっぱい。2010/10/06(水) 14:02:53
>>846,847
なんで、マニュアルに書いてあることを無視するん?
0850名無しさん@お腹いっぱい。2010/10/06(水) 20:27:44
テンプレにある、これが元凶だなw

>/bin/shプログラミング入門
>ttp://freebooks.info.nara-k.ac.jp/archive/ShellProgramming/?

つぎのスレから、削除するべき。
0851名無しさん@お腹いっぱい。2010/10/06(水) 20:33:17
>>841>>847
後ろから評価されるって思うには、どういう風に解釈すればいいの?

普通、2>&1 を「stderrにstdoutと同じにする」って読むと思うけど
これだと、前から後ろに順番に読まないと意味が合わないよね

読み方が違う?もっと根本的なところが違う?
0852名無しさん@お腹いっぱい。2010/10/06(水) 20:34:18
>>普通、2>&1 を「stderrをstdoutと同じにする」って読むと思うけど 
の間違い・・・
0853名無しさん@お腹いっぱい。2010/10/06(水) 20:54:30
foo 1>file 2>file
として、書き出される順番が揃わなくて考えこんだ日を思い出した
0854名無しさん@お腹いっぱい。2010/10/06(水) 23:17:59
>>852
言い直したところでその説明だと致命的におかしいのぜ。

ls -e 2>&1 >hoge.txt
のとき、標準エラー出力はhoge.txtに吐かれない。
「stderrにstdoutと同じにする」 と読んでしまったら
評価順序的にhoge.txtに吐かれないとおかしいだろ。
同じになったんだから。

「同じにする」という理解方法が間違い・
0855名無しさん@お腹いっぱい。2010/10/07(木) 00:11:24
1とか2は、「ファイルディスクリプタ」
 (ハンドルみたいなものかな?)

に対して、stdoutとかstderrは、「ファイル」そのもの。

これらを混同するから、わからなくなるだけ。



>>853
さらに、バファリンが絡んできて、わけわかめ?
0856名無しさん@お腹いっぱい。2010/10/07(木) 06:40:07
>>855
>stdoutとかstderrは、「ファイル」そのもの。

↑違うよ。

stdoutとかstderrはそれぞれファイル記述子1と2の別名。
例えば、hoge 2>&1 と、 hoge 2> /dev/stdout は同じ動作。

ファイルそのものはまた別。
0857名無しさん@お腹いっぱい。2010/10/07(木) 12:22:41
>>855
「FILEそのもの」と書きたかったのかな。

FILEは「ファイル」じゃなく「ファイルハンドル」
ファイルでスクリプタも、UNIX固有の特殊なファイルハンドル for システムコール。
0858名無しさん@お腹いっぱい。2010/10/07(木) 14:08:17
そういえば、標準エラー出力と標準出力を入れ替える手段って無くね?
0859名無しさん@お腹いっぱい。2010/10/07(木) 14:25:35
>>858
hoge 3>&2 2>&1 1>&3

じゃ駄目?
0860名無しさん@お腹いっぱい。2010/10/07(木) 14:36:36
>>859
うまくいった・・・

となると今までの評価順序の話は根底から崩れる予感。
&3 って誰だよって話
0861名無しさん@お腹いっぱい。2010/10/07(木) 14:38:14
もう面倒くさいから「後ろから評価される ように 動作する」でいいよ。
0862名無しさん@お腹いっぱい。2010/10/07(木) 14:47:10
>>861
「後ろから評価される ように 動作する」と考えると、
>>859 で stderrとstdoutを入れ換える動作が説明できない。
0863名無しさん@お腹いっぱい。2010/10/07(木) 14:50:32
>>860
> となると今までの評価順序の話は根底から崩れる予感。
> &3 って誰だよって話

最初から全然理解できてないだけじゃん。
0864名無しさん@お腹いっぱい。2010/10/07(木) 16:46:04
>>863
説明よろしくお願いします
0865名無しさん@お腹いっぱい。2010/10/07(木) 17:38:30
3>&2 : dup2(2,3) 3を2と同じところにつなぐ
2>&1 : dup2(1,2) 2を1と同じところにつなぐ(3は元の2の先(stderr)のまま)
1>&3 : dup2(3,1) 1を3と同じところにつなぐ(2は元の1の先(stdout)のまま)
0866名無しさん@お腹いっぱい。2010/10/07(木) 21:44:59
そんなことより、どう考えれば後ろから評価されるように
見えるのか教えてくれ
0867名無しさん@お腹いっぱい。2010/10/07(木) 23:06:21
>>866
自分で考えろよ
0868名無しさん@お腹いっぱい。2010/10/07(木) 23:13:57
(man 2 open , man 2 dup2 じゃ) いかんのか
0869名無しさん@お腹いっぱい。2010/10/07(木) 23:55:23
>>848 がdupを理解してないことはよくわかった。
これを簡潔に説明するのに必要なのはdupの勉強だから、
もう一度勉強し直せよw
0870名無しさん@お腹いっぱい。2010/10/08(金) 00:21:39
>>848
むしろ、なんで「釣られる」という発想になるのか俺には分からない

てきとーなプログラミング言語で
b = a
a = 1
としたときに、bにも1が代入されると思う?

それと全く理屈は同じなんだけどね

上の式のbをfd2、aをfd1と考えて欲しい
後でaに別の値を代入(リダイレクトによってfd1が参照するものを変える)したところで、b(fd2)の中身はかわらないよ
0871名無しさん@お腹いっぱい。2010/10/08(金) 00:24:05
後ろからとか前から評価とか意味がわからんから、
右結合とか左結合とか文法の言葉で語ってくれ。
0872名無しさん@お腹いっぱい。2010/10/08(金) 00:49:44
>>870
hoge 3>&2 2>&1 1>&3
&1,&b,&3をそれぞれa,b,cと置き換えると
b=c, a=b, c=a;
だろ。評価順に考えればこうなる。簡単な話だ。
0873名無しさん@お腹いっぱい。2010/10/08(金) 00:52:44
>>872
c=b
b=a
a=c
の間違いでは?
代入の向きが違う

3>&2 は、fd3にfd2をdupする(3に2を代入する)わけでしょ
0874名無しさん@お腹いっぱい。2010/10/08(金) 11:37:20
>>873
逆だろ・・・
0875名無しさん@お腹いっぱい。2010/10/08(金) 11:51:00
何いっての
0876名無しさん@お腹いっぱい。2010/10/08(金) 14:06:12
>>874
馬鹿だろ・・・
0877名無しさん@お腹いっぱい。2010/10/08(金) 14:38:12
>>874
なるほど、評価順以前に
これすら理解していない人が話をひっかきまわしていたのか
0878名無しさん@お腹いっぱい。2010/10/08(金) 19:21:10
(ハード) リンクの喩えのほうがいいかもな
発想の元は同じなわけだし
0879名無しさん@お腹いっぱい。2010/10/14(木) 16:51:17
初歩的な質問で申し訳ありません
bashです
whileが入れ子になってる関数で、2段目のwhileの中でセットされた変数が、その2段目のwhile
のループを抜けた時にクリアされてしまうのですが、これはそういう仕様なのでしょうか。
また、抜けても変数の値を保持するにはどうしたらよいでしょうか。
0880名無しさん@お腹いっぱい。2010/10/14(木) 17:40:41
意味がわかんないけど、

#!/usr/local/bin/bash
func () {
while :; do
while :; do
var=$1
break
done
echo $var
break
done
echo $var
}

func value
echo $var

で、valueが3回表示されないってこと?
0881名無しさん@お腹いっぱい。2010/10/14(木) 17:50:06
エスパーカが足りない。どうせサブシェル問題だろ
0882名無しさん@お腹いっぱい。2010/10/14(木) 17:50:09
>>880
そうです。
0883名無しさん@お腹いっぱい。2010/10/14(木) 17:54:35
>>881
あ、サブシェル問題だったんですね。よくわかりました。解決しました。
08848792010/10/14(木) 17:56:23
>>883
解決してません
0885名無しさん@お腹いっぱい。2010/10/14(木) 17:57:03
>>882は嘘か
08868792010/10/14(木) 18:00:55
http://search.luky.org/linux-users.9/msg06099.html
解決しました
0887名無しさん@お腹いっぱい。2010/10/14(木) 18:02:00
まーたサブシェル問題か
08888792010/10/14(木) 18:02:48
ケチケチすんなよなぁ兄弟
0889名無しさん@お腹いっぱい。2010/10/15(金) 15:46:10
bashの関数なんですが

function change_oppai {
if [ 〜 ];then
sed 's/AAA/oppai/g'
else
sed 's/BBB/oppai/g'
fi
}

この関数 change_oppai を標準入力に対応させるにはどうすればいいのでしょうか?

echo "AAA" | change_oppai -> oppai
0890名無しさん@お腹いっぱい。2010/10/15(金) 16:02:07
>>889
そのままで標準入力に対応してるけど。エスパー召喚?
0891名無しさん@お腹いっぱい。2010/10/15(金) 16:24:19
>function change_oppai {

bash でしか動かん。
昔からの関数定義と比べて機能が強化されたわけでもないのに、
なんで bash はつまらない非互換を導入したがるんだか。
0892名無しさん@お腹いっぱい。2010/10/15(金) 16:39:13
>>891
zshでもkshでも動きますが。何言ってんだか。
0893名無しさん@お腹いっぱい。2010/10/15(金) 17:29:28
bashで質問です。
ifで正規表現を使った判別を行っていますが、複数条件の時はどうすれば良いのでしょうか?

if [[ $i =~ ^foo ]]; then
 echo foobar
elif [[ $i =~ ^bar ]]; then
 echo foobar
fi

これのifとelifの条件式を一つにしたいのです、エラーになりますが、例えばこんな感じです。

if [[ $i =~ ^foo ] -o [ $i =~ ^bar ]]; then
 echo foobar
fi

よろしくご教授お願い致します。
0894名無しさん@お腹いっぱい。2010/10/15(金) 17:40:03
>>893
if [[ $i =? ^foo || $i =? ^bar ]]; then
0895名無しさん@お腹いっぱい。2010/10/15(金) 17:49:04
>>891
functionってわざわざ書くのが抵抗感あるかな。
函数って言うより、ただのサブルーチンだし。
0896名無しさん@お腹いっぱい。2010/10/15(金) 17:57:07
>>894
ありがとうございました。できました。
-oでなく、CやJavaで用いる||で良かったのですね。これなら覚え易いし、使い易いです。
=~と=?は同じでしょうか。これについては未だ不明なので調べてみます。
本当にありがとうございました。
0897名無しさん@お腹いっぱい。2010/10/15(金) 18:00:28
>>894 の「?」は文字化け。チルダーがなぜか化けてしか書き込めん。
0898名無しさん@お腹いっぱい。2010/10/15(金) 18:02:25
>>897
ありがとうございます。
なるほど、ではチルダで良いのですね。
重ね重ね本当にありがとうございました。
0899名無しさん@お腹いっぱい。2010/10/15(金) 18:53:41
>>879, >>889, >>893 は同じやつか?
0900名無しさん@お腹いっぱい。2010/10/18(月) 11:38:08
>>899
そう思った根拠は何だ?
0901名無しさん@お腹いっぱい。2010/10/18(月) 12:00:23
同じやつだったら何だというんだ。
0902名無しさん@お腹いっぱい。2010/10/18(月) 13:29:47
>>899
発言の趣旨を問いたい
0903名無しさん@お腹いっぱい。2010/10/24(日) 22:35:24
スクリプトの記述とは直接関係はしないけど
実務でシェルスクリプトを書く皆さんはコメントって結構意識して書いてますか?
0904名無しさん@お腹いっぱい。2010/10/24(日) 22:53:01
面白いと思って書いてるんだろうけどツマラン
0905名無しさん@お腹いっぱい。2010/10/25(月) 00:00:11
>>903
やる気と関係者のレベル次第。
素のUnixなんかでVimが入っていない場合だと、めんどくさい上にミスしやすくなるし。
0906名無しさん@お腹いっぱい。2010/10/25(月) 00:31:41
>>903
シェルに限らず業務用ソースはコメントを意識して多めに入れる
シェルに限って言えば・・・ascii(英語)でコメント書くことかな
0907名無しさん@お腹いっぱい。2010/10/25(月) 19:34:17
シェルはソースが読めてしまうので、
外に出すシェルは当然難読化処理してから出すよな。
コメントなんて論外。難読化のためのオトリコメントはアリだけど。
0908名無しさん@お腹いっぱい。2010/10/25(月) 19:39:31
は?
0909名無しさん@お腹いっぱい。2010/10/25(月) 19:43:50
>>907
難読化ツール何使ってる?
perl用みたいにぐちゃぐちゃになる奴ある?
0910名無しさん@お腹いっぱい。2010/10/25(月) 20:53:27
難読化というか、コードが汚いだけなんだけどね
0911名無しさん@お腹いっぱい。2010/10/25(月) 21:00:17
シェルスクリプトのコンパイラがあると
昔何かで読んだ記憶があるが
実物を目にした事はない
0912名無しさん@お腹いっぱい。2010/10/25(月) 21:25:19
configureの難読度ってどんなレベル?
0913名無しさん@お腹いっぱい。2010/10/25(月) 22:10:47
難読化って例えばこういうのだろ
実行すると hogeと表示



#!/bin/sh
h==;i=';';a=' ';t=e;e=v;s=a;q=l
$t$e$s$q$a"a${h}e${i}b${h}c${i}c${h}h${i}d${h}o${i}e${h}' '${i}f${h}g"
$a$b$c$d$e$c$d$f$a
0914名無しさん@お腹いっぱい。2010/10/25(月) 22:45:10
超絶に遅くなりそうだなw
java scriptなんかだと、難読化しながらサイズもコンパクトになるという二重のメリットがあったりするが。
0915名無しさん@お腹いっぱい。2010/10/29(金) 23:54:27
変数に*(アスタリスク)を入れるにはどうしたらいいでしょうか。

HOGE="\* foo"
として、
echo $HOGE
* foo
と出て欲しいのですが、
\* foo
になっちゃいます。
ヒアドキュメントのパターンもためしてみましたがうまくいかず・・・。
0916名無しさん@お腹いっぱい。2010/10/29(金) 23:57:20
困ったらeval
0917名無しさん@お腹いっぱい。2010/10/29(金) 23:58:19
echo "$HOGE" は?
dashとbashでは期待通り。
09189162010/10/29(金) 23:59:35
俺アホス
0919名無しさん@お腹いっぱい。2010/10/30(土) 00:26:15
HOGE='* foo'
echo "$HOGE"
0920名無しさん@お腹いっぱい。2010/10/30(土) 02:20:22
HOGE="* foo" echo "$HOGE"
0921名無しさん@お腹いっぱい。2010/10/30(土) 04:43:59
>>916-920
thanx

ヒアの場合は

HOGE=`cat <<'EOF'
* foo
* bar
EOF`

echo "$HOGE"

でいいのね。助かりマスタ。
0922名無しさん@お腹いっぱい。2010/10/30(土) 05:36:46
aaa
bbb
ccc

というテキストがあるとしてcatして変数にx="aaa bbb ccc"と入れたいんだけどどうやればいいですか?
シェルはbusyboxのashです。
0923名無しさん@お腹いっぱい。2010/10/30(土) 06:31:56
>>922
x="$(cat foo.txt | tr '\n' ' ')"
0924名無しさん@お腹いっぱい。2010/10/30(土) 07:48:54
>>922
x=`cat hoge.txt`
x=`echo $x`

わざとダブルクォートを付けずに echo $x して xに代入しなおすのがポイント
>>923 はtrコマンドが無駄。
0925名無しさん@お腹いっぱい。2010/10/30(土) 12:12:46
>>923>>924 のどちらが視認性があるか分かりますか? > >>924
あと、一旦 x に格納するだけ、無駄ですよね? > >>924
0926名無しさん@お腹いっぱい。2010/10/30(土) 12:31:59
xなんて使わずに、set -- `cat bar.txt`でいいじゃん。
0927名無しさん@お腹いっぱい。2010/10/30(土) 12:33:07
>>925
もちろん >>924 の方が視認性がある

一旦 x に格納は無駄じゃない。
外部コマンドの trを起動するオーバーヘッドの方がよっぽど無駄。
元質問はbusybox環境だから、trのないbusyboxだったらそもそも実行できない。

どうしても一旦 x に格納したくなければ

x=$(echo $(cat hoge.txt))
とすれば良いが、この方が視認性が落ちる。

よって、>>924 が最適解。
09289232010/10/30(土) 12:54:58
色々方法があるんだな 。

>>923の場合、最後に改行があるとcccの後にスペース入っちゃうし、改行が
\r\nだったら動かないとかあるんで、あんまりよくないとは思ってた。
0929名無しさん@お腹いっぱい。2010/10/30(土) 14:27:46
>>903
スクリプトを作れと頼まれればコメントを書くけど
何かの仕事を頼まれて、それ用にスクリプトを書いて
作ったときは書かない
0930名無しさん@お腹いっぱい。2010/10/30(土) 14:37:47
ashって$()使えるん?
0931名無しさん@お腹いっぱい。2010/10/30(土) 18:07:30
Kシェルでlsとかfindとかの返り値をもらえる方法があったら教えてください。
(検索に成功したら1とか)
0932名無しさん@お腹いっぱい。2010/10/30(土) 18:12:03
普通に $?
0933名無しさん@お腹いっぱい。2010/10/30(土) 18:54:04
そんな低レベルな質問であるはずがない。
もっと深読みするんだ。
0934名無しさん@お腹いっぱい。2010/10/30(土) 19:15:33
>>932
ありがd
0935名無しさん@お腹いっぱい。2010/11/01(月) 10:07:56
ファイルの中に一列

hoge1
hoge2
hoge3
hoge4
hoge5

というデータがあり、これを読んで

hoge1 hoge2 hoge3 hoge4 hoge5

と1行で出力するshシェルスクリプトを教えてください。
0936名無しさん@お腹いっぱい。2010/11/01(月) 10:16:29
echo `cat filename`
レス数が900を超えています。1000を超えると表示できなくなるよ。