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

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

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

前スレ
シェルスクリプト総合 その8
http://pc11.2ch.net/test/read.cgi/unix/1171517324/
0729名無しさん@お腹いっぱい。2008/01/05(土) 21:34:54
>>727
>>724は囲んでいるのではなく、'を連結しているだけ。 しかも>>728が指摘しているとおり無様。

>>728は一見囲んでいるようには見えるが、arg="'${hensu}''"でも通るので却下。
0730名無しさん@お腹いっぱい。2008/01/05(土) 21:37:28
追記:
>>728>>722の回答としては正しい。

> 'で囲まれるとパラメーター置換は行われない。
の反例としては却下。
0731名無しさん@お腹いっぱい。2008/01/05(土) 21:42:10
>>725
dd if=file bs=適当 skip=0 count=1 | gzip -c > 1.gz
dd if=file bs=適当 skip=1 count=1 | gzip -c > 2.gz
dd if=file bs=適当 skip=2 count=1 | gzip -c > 3.gz
cat ?.gz > file.gz

とやったfile.gzでも、gzip -dで全体が解凍できたわ。一方gzipをcompress/uncompressに
変えたら、ファイル蛾物故割れて解凍できなかった。圧縮時は単なるファイルの連結でも、
解凍時にgzipが連結ファイルであることを認識して、続きを解凍してくれてるんだな。
0732名無しさん@お腹いっぱい。2008/01/05(土) 23:03:18
>> 'で囲まれるとパラメーター置換は行われない。
>の反例としては却下。
却下
0733名無しさん@お腹いっぱい。2008/01/05(土) 23:57:08
>>732
↓これへの反論も出来ない池沼は黙ってればいいのに。
>>728は一見囲んでいるようには見えるが、arg="'${hensu}''"でも通るので却下。
0734名無しさん@お腹いっぱい。2008/01/06(日) 00:07:54
>>733
それがどうした。
却下
0735名無しさん@お腹いっぱい。2008/01/06(日) 12:52:56
指定ディレクトリ内の容量チェックについて、
du -sh 以外で高速な方法はないでしょうか。

ファイル数や容量が多い場合、
du -sh にかなり時間がかかることが多いためです。
0736名無しさん@お腹いっぱい。2008/01/06(日) 20:28:38
>>735
それらファイルの所有者を測定用ユーザにしてquotaを設定しとく
0737名無しさん@お腹いっぱい。2008/01/07(月) 02:33:08
変数に変数を入れたいです。

n=1
var${n}=foo
echo var1=foo

直接はできないっぽいんですが、こういう時の上手い手ってありますか?
0738名無しさん@お腹いっぱい。2008/01/07(月) 02:59:13
>>737
eval var$n=foo
07397372008/01/08(火) 02:38:23
>>738
目から鱗でした
0740名無しさん@お腹いっぱい。2008/01/08(火) 16:30:29
shスクリプトを作成して、inetd経由で叩こうとしてますが、
shスクリプトの中で、readで読んだ変数に改行コードらしきコードが入っていて、
うまく処理が動きません。

シェル変数 AAA,BBBの最後の1バイトを取ってあげれば動くと思うんですが、
どうやれば良いでしょうか?

以下がサンプルのスクリプトです。
コマンドラインで起動すると、PATH_VARは、キーボードから入力した2つの文字列が
'/'で連結されて表示されるのですが、これをinetd経由でtelnetから起動すると、
PATH_VARが変な文字(シェル変数AAAが設定されない?)となってしまいます。

#!/bin/sh
read AAA
read BBB
PATH_VAR="$AAA/$BBB"
echo $PATH_VAR

0741名無しさん@お腹いっぱい。2008/01/08(火) 16:38:40
>>740
readで読み込むと、改行コードは自動的に取り除かれる。
問題になってるのは、改行 \n じゃなくて 復帰 \r (^M) じゃないのかな

^M を取り除くには tr とか使う。
0742名無しさん@お腹いっぱい。2008/01/08(火) 16:44:33
>>740

read AAA
read BBB
PATH_VAR=`echo "$AAA/$BBB" | tr -d '\015'`
echo $PATH_VAR
0743名無しさん@お腹いっぱい。2008/01/08(火) 16:59:36
>>742
THXです。
おっしゃる通り、改行ではなく復帰でした。
だから、PATH_VARを表示した時に、AAAが表示されなかったんですね。
大変助かりました、どうもありがとうございました。

改修バージョンはこんな感じになりました。
#!/bin/sh
read line ; AAA=`echo $line | tr -d \\\r`
read line ; BBB=`echo $line | tr -d \\\r`
PATH_VAR="$AAA/$BBB"
echo $PATH_VAR
0744名無しさん@お腹いっぱい。2008/01/08(火) 17:48:07
なんかおかしい、制御文字? と思ったら、hexdump -Cに食わせてみると良い。
0745名無しさん@お腹いっぱい。2008/01/08(火) 19:03:22
>>753
そういうやり方もありですね。

>>745
echo $AAA | hd
ってやるとちゃんと制御コードが確認出来ました。

シェル変数の中身ってこうすればHEXでみれたんですね。
\とか、"とか、'とか、`とかをシェル変数に突っ込むときに、
いつも困ってたんですが、良いこと聞きました。
ありがとう。
0746名無しさん@お腹いっぱい。2008/01/09(水) 13:39:56
hd -c
0747名無しさん@お腹いっぱい。2008/01/09(水) 13:45:28
hdコマンドというのは FreeBSD方言なわけだが、、

よりポータブルには、od -Ax -t x1 だな。
0748名無しさん@お腹いっぱい。2008/01/17(木) 00:04:48
コンマで区切った各データを変数に入れるにはどうしたらいいんでしょうか?
0749名無しさん@お腹いっぱい。2008/01/17(木) 00:23:08
IFS=,
read v1 v2 v3
0750名無しさん@お腹いっぱい。2008/01/17(木) 01:03:42
bash 限定
read -d ,
0751名無しさん@お腹いっぱい。2008/01/17(木) 03:52:18
シェルの話じゃないかもしれませんが、もし適当なスレがあったら誘導してくださいませ

find . -type f -regex ".*\.[ch]\(pp\|xx\)?"
で*.cppとか.hだけを列挙できるわけですが
updatedbの--findoptionsに
updatedb --findoptions='-type f -regex ".*\.[ch]\(pp\|xx\)?"' --localpath='./' --output='/home/someone/sources.db'
などと同様に指定してもうまくフィルタリングされません(上のコマンドで生成されたものを使うと普通にディレクトリ名や要らないファイルが引っかかる)
どうにかupdatedbで生成されるデータベースの内容をコントロールする手は無いんでしょうか?
0752名無しさん@お腹いっぱい。2008/01/18(金) 00:42:15
>>751
そんなオプションがあるんだ。
プラットフォームは何?

クォートに問題がある気がするんだけど、これならどう?
--findoptions="-type f -regex \".*\.[ch]\(pp\|xx\)?\""

0753名無しさん@お腹いっぱい。2008/01/18(金) 22:20:53
実際にどういう引数がfindに渡っているか調べればいい。
OSによって違うだろうけど道具はあるはず。
多少牛刀な気もするがシステムコールのトレースとか。
0754名無しさん@お腹いっぱい。2008/01/19(土) 00:57:26
牛刀ってなに?
おっぱいが牛みたいな可愛い女の子剣士?
0755名無しさん@お腹いっぱい。2008/01/19(土) 02:36:19
>>754
1. 「牛をぶった切るための刀」
2. 「牛刀をもって鶏を割く」の略
3. 「おっぱいが牛みたいな可愛い女の子剣士」

好きなの選べ
0756名無しさん@お腹いっぱい。2008/01/19(土) 02:55:18
実際にどういう引数がfindに渡っているか調べればいい。
OSによって違うだろうけど道具はあるはず。
多少おっぱいが牛みたいな可愛い女の子剣士な気もするがシステムコールのトレースとか。
0757名無しさん@お腹いっぱい。2008/01/19(土) 10:17:30
システムコールのトレースは牛刀。

実装によるが、updatedbからのfindの呼び出しが、絶対PATHじゃないなら、
findの偽物スクリプトを作って、PATHを先に通して
引数を表示させれば良い。

#!/bin/sh
echo "$@"

みたいな。

絶対PATHの場合はちょっと厄介だが、
/usr/bin/findを一時的にリネームして、偽物findスクリプトに置き換える。
0758名無しさん@お腹いっぱい。2008/01/19(土) 10:51:51
新しめのupdatedbはfindを呼ばなくなってた…みたいなオチではありませんように
0759名無しさん@お腹いっぱい。2008/01/19(土) 10:53:30
>>757

>絶対PATHの場合はちょっと厄介だが、
>/usr/bin/findを一時的にリネームして、偽物findスクリプトに置き換える。
 客先でそれやった馬鹿がいた。しかも本番環境で……
 cronで動いていた業務処理が止まり、大騒ぎに。
0760名無しさん@お腹いっぱい。2008/01/19(土) 11:01:09
>759 ちゃんと本物にも渡すようにしとくのがたしなみだよなwww
#!/bin/sh
echo $@
find $@
0761名無しさん@お腹いっぱい。2008/01/19(土) 11:12:19
そもそも、本番環境の/usr/binの下に変更を加えちゃダメでしょ?
そ〜ゆ〜のは、テスト環境でやるもの。
0762名無しさん@お腹いっぱい。2008/01/19(土) 11:18:48
>>761 どこから本番環境とかテスト環境とかがでてきたんだ?
0763名無しさん@お腹いっぱい。2008/01/19(土) 12:02:32
>>760
それ、スクリプト無限ループw 釣りか?
あと、$@ は "$@" にしないと $@ の意味をなさない。
0764名無しさん@お腹いっぱい。2008/01/19(土) 12:30:00
>763 ループはネタのつもりだったが,クオーテションは素だったwww恥ずかしいwww
0765名無しさん@お腹いっぱい。2008/01/19(土) 13:17:50
すぐに終わるもんじゃなし、 手で実行して、psで分かるだろw
0766名無しさん@お腹いっぱい。2008/01/19(土) 13:26:50
まさかシステムコールのトレースが牛刀だといって757みたいな馬鹿が出てくるとは
思いもよらなかった。
execをすり替えてロギングするライブラリ作ってLD_PRELOADあたりを
想定していたんだが。
0767名無しさん@お腹いっぱい。2008/01/19(土) 13:40:24
>>766
LD_PRELOAD だと、コンパイルが必要。
シェルスクリプトでできるものはシェルスクリプトで済ませる方がエレガント。

まさかとは思うが、>>766 は wrapper scriptの類を、
いちいちexecv() とかで書いてコンパイルしてるのかな?
0768名無しさん@お腹いっぱい。2008/01/19(土) 13:50:17
>>767 /etc/libmap.conf
つか, あるもん使えばいいんじゃね?
0769名無しさん@お腹いっぱい。2008/01/19(土) 13:52:31
>>768
それと、「コンパイル不要」とがどう結び付くんだよ。
あと、FreeBSD限定の話をされてもな
0770名無しさん@お腹いっぱい。2008/01/19(土) 14:40:32
>>767
そんな面倒な事しなくても DTrace 使えば良いじゃない
0771名無しさん@お腹いっぱい。2008/01/19(土) 17:16:19
シェルスクリプトの本で実用例の多い本ってありませんか?
0772名無しさん@お腹いっぱい。2008/01/19(土) 17:28:10
>>762

>>759
> 客先でそれやった馬鹿がいた。しかも本番環境で……
0773名無しさん@お腹いっぱい。2008/01/19(土) 17:39:20
>>770
それこそおっぱいが牛みたいな可愛い女の子剣士だろ
0774名無しさん@お腹いっぱい。2008/01/19(土) 17:47:03
おっぱいが剣みたいな可愛い女の子牛士
0775名無しさん@お腹いっぱい。2008/01/19(土) 23:12:58
おっぱいスキデス

Cron+Cシェルで
  http://www.hoge.com/hoge.php 
を実行するのを書かなきゃいけなくなってしまいました。

1:同一サーバー内の、hoge.phpを実行するにはなんて書けばいいでしょうか?
 SHELL=/bin/csh
 ** Cronの設定 **
  /home/*****/www.hoge.com/hoge.php

2:外部のサーバー(これもCシェル)からからの場合は、http〜と直接書けるのでしょうか?
 SHELL=/bin/csh
 ** Cronの設定 **
http://www.hoge.com/hoge.php #OK?
0776名無しさん@お腹いっぱい。2008/01/19(土) 23:42:58
知識がスクリプト以前に、コマンドライン未満なんだが… とりあえずwgetのマニュアルでも読んで。
0777名無しさん@お腹いっぱい。2008/01/19(土) 23:49:02
釣りだろ、ちょっと面白かった。
0778名無しさん@お腹いっぱい。2008/01/19(土) 23:52:42
ちゃんと hoge.com にドメイン借用許可もらってるんだろな
0779名無しさん@お腹いっぱい。2008/01/19(土) 23:53:08
まず、cshを捨てる技術から憶えよう。
07807752008/01/20(日) 00:35:39
>>779
わかった、じゃぁ、tcshつかうよ
07817752008/01/20(日) 01:03:14
(o*。_。)oペコッ

解決しました。 wgetのそういう使い方もあるんですね。
Cshなのは、鯖屋さんの関係です。
0782名無しさん@お腹いっぱい。2008/01/25(金) 22:42:49
ポータブルに乱数を得るにはどうするのが一番いい?
使えそうなのはawkくらいだが、こいつは秒が変わる前に二度呼ぶと
同じ値を返してしまう。
awk 'BEGIN{srand();print rand()}'
$RANDOMはbash依存。jotはBSD系。/dev/randomもあるかどうかわからん。
perl -e 'print rand()'が一番ましだろうか。
0783名無しさん@お腹いっぱい。2008/01/25(金) 22:50:06
>>782
exprで乱数計算。
0784名無しさん@お腹いっぱい。2008/01/26(土) 00:42:39
452 名前:login:Penguin[sage] 投稿日:2008/01/16(水) 22:47:32 ID:HQvmxN1E
dateのmanを見ていたら、

 %N nanoseconds (000000000..999999999)

というのがあった。こんな感じ

% echo -n `date +%N`
431218994 % echo -n `date +%N`
857494685 % echo -n `date +%N`
269031777 % echo -n `date +%N`
803351248 % echo -n `date +%N`
195538275 % echo -n `date +%N`
538357509 % echo -n `date +%N`
058776188 %

453 名前:login:Penguin[sage] 投稿日:2008/01/16(水) 23:09:59 ID:PJonPFmQ
jotはたぶんBSD系限定だよな。
jot -r 10 1 6

/dev/urandomは10進数テキストで得るのがめんどーだろうか。 
dd if=/dev/urandom bs=2 count=1 2>/dev/null | od -vd

左カラムがじゃまだな。 sed 1q |cut -f2 -d' ' とかで削るか。

454 名前:login:Penguin[sage] 投稿日:2008/01/16(水) 23:21:36 ID:KAlEWwYc
>452,453 なるほど.date +%Nはいい感じ.
jot便利そうだよ,jot.犬にもこんなの欲しいな.
ありがとう

455 名前:login:Penguin[sage] 投稿日:2008/01/16(水) 23:24:18 ID:HQvmxN1E
od -t u1 /dev/urandom | awk '{print $2;exit}'
0785名無しさん@お腹いっぱい。2008/01/26(土) 09:53:03
おいおい、date +%N はポータブルじゃないよ。GNU限定かな。
0786名無しさん@お腹いっぱい。2008/01/26(土) 10:44:55
awk 'BEGIN{srand(('`sh -c 'echo $$'`+`date +%s`');rand();print rand()}'
でどうよ。
余計なrand()一発は、FreeBSDの実装で、srand直後のrandがおかしいため。
+%sもない前時代までポータブルにしないといかんか?
0787名無しさん@お腹いっぱい。2008/01/26(土) 11:19:04
>>786
じゃあ、date +%s がない Solaris10 は前時代のOSなんだw
0788名無しさん@お腹いっぱい。2008/01/26(土) 12:24:46
>>787
シーラカンスだろ
0789名無しさん@お腹いっぱい。2008/01/26(土) 14:52:38
>>788 は Solaris1.xと混同してる悪寒。
0790名無しさん@お腹いっぱい。2008/01/26(土) 15:07:36
*BSDとlinuxでさえ動けば,他のUNIX使ってる人は自分で勝手になんとかしてくれると思うwww
0791名無しさん@お腹いっぱい。2008/01/26(土) 23:11:38
rm -rコマンドを使用して、「*.txt」以外の
全てのディレクトリ・ファイルを削除したい
http://virus.okwave.jp/qa2500406.html

こいつは馬鹿なの?
http://virus.okwave.jp/user.php3?u=296068

というかなんでこれが良解答なの?
0792名無しさん@お腹いっぱい。2008/01/26(土) 23:26:41
*.txt以外のファイルを取得する部分は
find . ! -name '*.txt'
でいいかな?
0793名無しさん@お腹いっぱい。2008/01/26(土) 23:45:55
そもそも*.txtがあるディレクトリは削除できないので、
> rm -rコマンドを使用して、「*.txt」以外の
> 全てのディレクトリ・ファイルを削除したい
という要求は実現不可能。*.txtを含むディレクトリは除外なら

find . -depth -not -name '*.txt' -a \( -type d -a -empty -o -type f \) -exec rm -rf '{}' ';'
0794名無しさん@お腹いっぱい。2008/01/29(火) 23:10:16
>>791
> というかなんでこれが良解答なの?

一般人しかいないQAサイトじゃそんなもんだろ。
0795名無しさん@お腹いっぱい。2008/01/30(水) 03:01:04
while read のファイル読み込み処理の中で <enter>の入力待ちさせたい時って
みんなどうやってる?
普通に read DUMMY 入れたらバッファである<STDIN>から一行取られて終わり
だよね。
forで回避 or 子shellに分ける以外に俺の行く道はないんすかね?

==== hoge.sh START ================
#!/bin/sh
cat << EOF > ./hoge.list
AAA
BBB
CCC
DDD
EOF

while read i
do
 echo "$i"
 echo "<push enter>"
 read DUMMY
done < ./hoge.list
==== hoge.sh END ======================


ちょっと気になってググったら
ttp://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=34340&forum=10&2
>試しましたが、できましたよ。
とか回答してるやつがいた。

まじすか?
0796名無しさん@お腹いっぱい。2008/01/30(水) 04:29:25
>>795
/dev/ttyを使えばプロセスの制御端末から読める。
read _ </dev/tty

例:
head foo.txt |sh -c 'i=1;while read -r l; do printf "%3d: %s\n" $i "$l";i=$((i + 1)); read _ </dev/tty; done'
0797名無しさん@お腹いっぱい。2008/01/30(水) 05:04:54
>>795
>>796 の方が素直だが、別の fd を用意する方法もある。
例えば、ファイルを fd3 から読むのなら、こんなかんじ。

exec 3< "./hoge.list "
while read i 0<&3
do
 echo "$i"
 echo "<push enter>"
 read DUMMY
done
07987952008/01/30(水) 09:17:51
>>796 >>797
おおー その手がありましたか。
ありがとうございます。
0799名無しさん@お腹いっぱい。2008/02/01(金) 21:46:35
別段困っているわけではないのですが、

~/.forwardをバックアップするスクリプトを書いてたのですが、

最初これでいいかなと思ったのですが、
cd /home; tar cvf /tmp/tmp.tar */.forward

よく考えたらユーザ数が非常に多い環境ではエラーになります。
それで試行錯誤して、こうしたのですが、

( cd /home ; find . -name .forward -maxdepth 2 -print | tar cvf /tmp/tmp.tar -T - )

エレガントではない。もっと綺麗な書き方はないですかね。
0800名無しさん@お腹いっぱい。2008/02/01(金) 21:48:51
補足。 -maxdepth を指定しているのは、各ユーザの
ホーム直下以外に .forward というファイルがあるから
です。
0801名無しさん@お腹いっぱい。2008/02/01(金) 21:55:29
それで充分だと思うが.
というかエレガントでないとも思わないが.
0802名無しさん@お腹いっぱい。2008/02/01(金) 21:58:01
find の -maxdepth と、tar の -T がポータブルじゃないのがノンエレガントだな。
08037992008/02/01(金) 23:22:55
>>801
コマンドの長さが2倍になったのが気に入らなかったのです。

>>802
そこまで気が回らなかった。
0804名無しさん@お腹いっぱい。2008/02/01(金) 23:41:07
気が回らなかったっていうより気にする必要がなかったんじゃないの。
状況限定だろうし。あえていうなら-Tよりは-Iの方がポータブル?
08057992008/02/01(金) 23:53:10
>>804 気にする必要がなかったんじゃないの

いやま、それを言うなら、うちはユーザ数が400名程度だから、
事実上、これでも全く問題ないわけなんです。

cd /home; tar cvf /tmp/tmp.tar */.forward

shellの引数の最大値は幾つぐらいだったか忘れたけど、数千のオーダーだろうし。
0806名無しさん@お腹いっぱい。2008/02/02(土) 00:18:03
cpio使え。
0807名無しさん@お腹いっぱい。2008/02/02(土) 07:19:21
質問です。
以下のように変数にスペースを含む文字列(ファイル名)を入れ、それを
別の変数の定義に使おうとしています。

FILE="foo bar.txt"
FLAGS="-l $FILE"
ls $FLAGS

しかしこれだとうまくいきません。

foo: No such file or directory
bar.txt: No such file or directory

ほかに FLAGS="-l \"$FILE\"" とか ls "$FLAGS" とか試しましたが
間違いでした。
どう書けばいいのでしょう?
0808名無しさん@お腹いっぱい。2008/02/02(土) 07:41:41
>>807
FLAGS="-l '$FILE'"

だけどその例だと
FLAGS="-l"
ls $FLAGS "$FILE"
の方が適当なんじゃないの。

別解としては
FLAGS='-l "$FILE"'
eval ls $FLAGS
0809名無しさん@お腹いっぱい。2008/02/02(土) 08:29:20
>>807
>しかしこれだとうまくいきません。
これはこれで、うまくいってるよ。
No such file or directory(そんなファイルやディレクトリはないよ)
と言われてるんだから、単にカレントディレクトリに foo と bar.txt が無いだけだよ。

正しくは >>808 の言う通りだと思う。
0810名無しさん@お腹いっぱい。2008/02/02(土) 10:19:27
FILE="foo bat.txt"
set -- -l
set ${1+"$@"} "$FILE"

ls ${1+"$@"}
0811名無しさん@お腹いっぱい。2008/02/02(土) 10:44:29
>>810
明らかに1つ以上 setしてるんだから、${1+"$@"} なんて書き方する必要なし。
"$@" だけでOK。

あと、引数が0の場合であっても現行のシェルなら "$@" ですべてOK。
${1+"$@"} という書き方はもう古いので、そろそろ撲滅すべし。
0812名無しさん@お腹いっぱい。2008/02/02(土) 11:12:57
これ
set -- -l
と、これ
FILE="foo bat.txt"
と、これ
set ${1+"$@"} "$FILE"
ls ${1+"$@"}
が、別々のモジュールになるかも知れないので、安全な方に倒すのが当然だね。
お前のプログラムってバグだらけだろう。

> ${1+"$@"} という書き方はもう古いので、そろそろ撲滅すべし。
Solaris10ではまだ必要。
0813名無しさん@お腹いっぱい。2008/02/02(土) 11:34:33
>>812
>Solaris10ではまだ必要。

嘘書くな。Solaris10上で、$# = 0 の状態で "$@" が問題なく消えてくれる
(空文字列が残らない)ことは確認済み。

${1+"$@"}が必要なようなシェルは今は残っていない。
0814名無しさん@お腹いっぱい。2008/02/02(土) 11:50:01
>>813
条件はSolaris10じゃなかった。
set -uされている状態で使われる可能性がある場合。
0815名無しさん@お腹いっぱい。2008/02/02(土) 12:04:03
>>814
言うと思った。set -u の話なんて誰もしてない。後出し乙

結論: ${1+"$@"} は不要
0816名無しさん@お腹いっぱい。2008/02/02(土) 12:06:40
> 言うと思った。set -u の話なんて誰もしてない。後出し乙
これを後出しと言わずして、何を後出しといおうか… 大笑い。
0817名無しさん@お腹いっぱい。2008/02/02(土) 12:13:13
むしろ、Solaris で set -u の時 "$@" がおかしくなるのは
Solarisのバグだと思うぞ。

そもそも set -u なんてすることは滅多にないし、そういう意味でも "$@" 推奨。
0818名無しさん@お腹いっぱい。2008/02/02(土) 12:21:52
元の質問は >>807 なわけだ。
そこには、
引数が0個の場合とか、
シェルスクリプトが別ファイルにわかれる場合とか、
set -uする場合とか、
一切書いていない。

勝手な条件を後出しで付け加えたのは >>810

さらに言うと、>>810 の方法では位置パラメータが破壊されるから
そもそも setを使うのは効果的じゃない。そんなことしなくてもできるし。
0819名無しさん@お腹いっぱい。2008/02/02(土) 12:38:45
>>817
ashでも
@: parameter not set
という警告がでるが。
> そもそも set -u なんてすることは滅多にないし、そういう意味でも "$@" 推奨。
お前perlでuse strictしないの? ダメな奴だな。

>>818
後出しでケチつけていくのがみっともない。しかも致命的な欠陥の指摘じゃないから反論される。

> さらに言うと、>>810 の方法では位置パラメータが破壊されるから
破壊されても問題ない場合や、シェルファンクションで使える。

> そもそも setを使うのは効果的じゃない。
根拠なし。

> そんなことしなくてもできるし。
別解という言葉を調べてみることをお勧めする。
0820名無しさん@お腹いっぱい。2008/02/02(土) 12:44:48
>>819
$ ash
$ set -u
$ echo $#
0
$ echo "$@"

$

問題なしw
0821名無しさん@お腹いっぱい。2008/02/02(土) 12:54:11
$ uname -a
FreeBSD orz 8.0-CURRENT FreeBSD 8.0-CURRENT #1: Tue Jan 29 01:35:03 JST 2008 root@:/usr/obj/src/sys/orz i386

$ sh
$ set -u
$ echo $#
0
$ echo "$@"
@: parameter not set

実例が提示されたので、以下は嘘。
> ${1+"$@"}が必要なようなシェルは今は残っていない。
0822名無しさん@お腹いっぱい。2008/02/02(土) 12:59:31
>>821
だから、set -u の話は後出し

> ${1+"$@"}が必要なようなシェルは今は残っていない。

のは、"$@" が "" (空文字列) に展開されるような古いシェルのこと。

よって、
> ${1+"$@"}が必要なようなシェルは今は残っていない。
は、正しい。
0823名無しさん@お腹いっぱい。2008/02/02(土) 13:06:51
> のは、"$@" が "" (空文字列) に展開されるような古いシェルのこと。
ハイハイ、後出し。wwww

> ${1+"$@"}が必要なようなシェルは今は残っていない。
これは嘘。
0824名無しさん@お腹いっぱい。2008/02/02(土) 13:14:38
>>812 では、
${1+"$@"}が必要な理由として、

set -- -l と FILE="foo bat.txt" と、set ${1+"$@"} が
別々のモジュールになるかも知れないので、

と言っている。
これは、引数が0個になる場合があるから、と言う意味に他ならない。

それに対する反論として、
>>813 で、${1+"$@"} は不要と言っている。

その「後」で、>>814 が set -u の話を持ち出している。

よって、>>814 の set -u が後出し。

あと、未だに set -u で "$@" がエラーになる FreeBSDもバグ持ちと言うことだな。
0825名無しさん@お腹いっぱい。2008/02/02(土) 13:20:24
>>807が前提条件全部出さないのが悪い。
0826名無しさん@お腹いっぱい。2008/02/02(土) 13:27:40
・set -- -l と FILE="foo bat.txt" と、set ${1+"$@"} が別モジュールになる。
・set -uで警告が出る(ので回避する)
は排他じゃない。

>>811は、${1+"$@"}を空文字列への展開を避けるためと思い込んで、突っ込み(>>811)を
入れたのはいいが、set -uでの警告を知らなかったため、しどろもどろで反論を続けている。
かなり見苦しいぞ。www

> あと、未だに set -u で "$@" がエラーになる FreeBSDもバグ持ちと言うことだな。
FreeBSDだけじゃなく、Solaris10でも同じように警告が出るぞ。

ところで、お前が試したashって何処のashだよ。
ash -> bashじゃねーのか? www
0827名無しさん@お腹いっぱい。2008/02/02(土) 14:21:04
ちょっとここまでの流れを誰かわかりやすく説明してくれwwww
0828名無しさん@お腹いっぱい。2008/02/02(土) 14:42:22
>>810 位置パラメータを用いた別解をだす。
>>811 ${1+"$@"}という記法に因縁つける。
>>810 反論のついでに「お前のプログラムってバグだらけだろう。」と煽る。>>812
>>811 必死の再反論を試みるが迎撃され、逃亡。 <<=== 今ココ
0829名無しさん@お腹いっぱい。2008/02/02(土) 15:06:57
${1+"$@"}の意味がわからない俺は間違いなくゆとりlinux使い\(^o^)/
■ このスレッドは過去ログ倉庫に格納されています