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

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

レス数が950を超えています。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
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`
0937名無しさん@お腹いっぱい。2010/11/01(月) 10:54:01
> shシェルスクリプト
ちょっと斬新。
0938名無しさん@お腹いっぱい。2010/11/01(月) 11:49:54
ファイルサイズがでかい時は、

while read x; do echo -n "$x "; done < filename | sed 's/ $//'

0939名無しさん@お腹いっぱい。2010/11/01(月) 11:59:54
tr '¥012' ' ' < text
じゃだめなん?

あ、最後の改行まで落ちるか。
0940名無しさん@お腹いっぱい。2010/11/01(月) 12:11:01
paste -sd' ' filename
0941名無しさん@お腹いっぱい。2010/11/01(月) 12:13:07
pasteとかtrなんて存在すら忘れてた
0942名無しさん@お腹いっぱい。2010/11/01(月) 21:22:51
shがシェルの1つだから、shスクリプトのほうがわかりやすいな
09439232010/11/01(月) 23:22:06
x="$(cat test.txt | tr '\n' ')"

打ち間違えて ' が一つ足りませんでした。
>
が延々と出てCtrl+Cでも終了できません
お助けください orz
09449232010/11/01(月) 23:24:33
>)"
と打ったら終了できました。
とりあえずスレ汚しすいません。。。
0945名無しさん@お腹いっぱい。2010/11/01(月) 23:25:48
たぶん Ctrl-D(End of File) でもイケた気がする。
Ctrl-Cは動いてるプロセスに 止まれよ! と通知するやつだから、
まだコマンド発行してない段階では通用しないわさ。
0946名無しさん@お腹いっぱい。2010/11/01(月) 23:26:23
>>943
だから 視認性(笑) がある >>924 の方を使えとあれほど、、


普通のシェルなら Ctrl+Cで終了できるよ。
クォートの途中を表す > プロンプトが出てるだけだから。
0947名無しさん@お腹いっぱい。2010/11/01(月) 23:29:13
zshもbashもCtrl-Cで止まったわ。

09489222010/11/01(月) 23:30:54
あ。自分は>>922でした orz
>>923,924さんの方の両方で出来ました。
>>927さん詳しい解説と環境のご配慮までありがとうございます。
busybox-1.17.1で tr のアプレットまで入っているようです。
オプションは -c -d -s しかありませんでしたけど。

皆さん本当にありがとうございました。
またスレ汚しすいませんでした。
0949名無しさん@お腹いっぱい。2010/11/01(月) 23:34:25
おおう、そういえばbusyboxのシェルだったか。
0950名無しさん@お腹いっぱい。2010/11/02(火) 01:53:36
grep(egrep)でCRLFの改行コードの検索をやりたいのですが、
od -c hoge.txt | egrep '\\\n \\\r'
だと
0000000 a a a a a a a a a a a a a a a \n
0000020 \r
のように改行をまたいだ場合に検索できません。

この場合もCRLFを検索するにはどうすればいいのでしょうか?
0951名無しさん@お腹いっぱい。2010/11/02(火) 02:11:06
以下のようなバックアップスクリプトを作ってみたんだが
圧縮したあとに展開したら元ファイルとファイルサイズが全然違う
どうしてかわかるエロイ人いませんか

#!/bin/sh

PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin

KEEPDAY=90

BK_DIR=/home/hoge/www
PUT_DIR=/home/hoge/backup/www

MKFILE=www.`date +'%y%m%d'`
TGZFILE=$MKFILE.tar.gz
RMFILE=www.`date -v -"$KEEPDAY"d +'%y%m%d'`.tar.gz

cd $BK_DIR
echo "Packing to $MKFILE"
tar cvzf $TGZFILE ./

echo "Checking to $TGZFILE"
if [ -f $TGZFILE -a -f $RMFILE ]; then
rm -f $RMFILE
echo "Removed $RMFILE"
exit 0
fi
0952名無しさん@お腹いっぱい。2010/11/02(火) 08:27:22
バックアップしたいディレクトリの中にバックアップファイル作っちゃうの?
0953名無しさん@お腹いっぱい。2010/11/02(火) 08:48:16
>>950
nとr逆じゃね?
CRLF = ^M^J なので、少なくとも改行が CRLFかLF だと分かっていれば
grep "^M$" < hoge.txt
でいいんじゃ?
(^MはCtrl押しながらmを打鍵)
0954名無しさん@お腹いっぱい。2010/11/02(火) 08:59:21
環境(エディタ、端末)にもよるけど、普通 Ctrl+m = Enter じゃね?
Ctrl+v Ctrl+m で入れる環境が多いと思うけど。
0955名無しさん@お腹いっぱい。2010/11/02(火) 09:05:38
すまん、確かにCtrl-Vの前置を書き忘れていた。
09569352010/11/02(火) 17:55:13
>>936-942
レスありがとうございます。
勉強になりました。
0957名無しさん@お腹いっぱい。2010/11/03(水) 00:00:04
>>953-955
ありがとうございます。
出来ました。

nとr逆ですね。

cat -v hoge
で見える改行コードの入力の仕方がわからなかったので助かりました。

しかし、grepって複数行の検索出来ないんですね。
0958名無しさん@お腹いっぱい。2010/11/03(水) 00:02:35
>>952
バックアップしたいディレクトリをフルパスで指定すると
tarのエラーで/を先頭に付けるな
と、怒られてしまったので

cdでバックアップ元のディレクトリに移動

./でバックアップ元を指定して、バックアップ先へtar.gzで圧縮

という流れにしました

もっと良い書き方があるんだろうけどターミナル触るのが久々
過ぎてこんなぐらいしか思いつかなかった

もっと良い書き方はございますか
0959名無しさん@お腹いっぱい。2010/11/03(水) 00:11:01
ございます
0960名無しさん@お腹いっぱい。2010/11/03(水) 00:46:05
>>958
manぐらい読めよ。
0961名無しさん@お腹いっぱい。2010/11/03(水) 02:03:21
(cd /hoge/hoge; tar cf - *) はいろいろ応用が利く。
最近はcdできるtarもいろいろあるけど。
0962名無しさん@お腹いっぱい。2010/11/03(水) 09:21:44
-C ってSolarisにさえあるし、相当古いtarからなかったっけ
0963名無しさん@お腹いっぱい。2010/11/03(水) 12:08:56
じゃあかなりポータブルだと思っていいのか。

今更だが、 tar cf - -C /hoge/huga * とサブシェル内cdだと*の展開タイミング
が違うので、同じ投稿に並べて書いたのは不適切だったな。
0964名無しさん@お腹いっぱい。2010/11/03(水) 19:05:58
>(cd /hoge/hoge; tar cf - *) はいろいろ応用が利く。

; じゃなくて && にすべし。; だと間違えて権限のないディレクトリに
cd しようとして失敗しても、カレントディレクトリのまま tar が実行されてしまうので、
場合によっては意図しないファイルを上書きして消すなんて事故が起きることがある。

というか、そういう事故を起こさないためにも -C を使ったほうがいい。
09659512010/11/05(金) 00:11:31
>>964
確かにその方がいいですね
仕事でやってる時は事故を起こさないようにそうしてた気がします

ところでファイルサイズ違う件について心当たりある方いま(ry

その後もググって見たけど相変わらずわからずで
何回もスレ汚しスマソ
0966名無しさん@お腹いっぱい。2010/11/05(金) 00:59:32
もっと具体的に書けや
0967名無しさん@お腹いっぱい。2010/11/05(金) 08:36:34
複数のマシンを一度に再起動をかけたいのですが、どのような方法があるでしょうか?
0968名無しさん@お腹いっぱい。2010/11/05(金) 12:06:27
>>965
何のファイルサイズがどう違うの?
レス数が950を超えています。1000を超えると書き込みができなくなります。