シェルスクリプト総合 その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これを簡潔に説明するのに必要なのはdupの勉強だから、
もう一度勉強し直せよw
0870名無しさん@お腹いっぱい。
2010/10/08(金) 00:21:39むしろ、なんで「釣られる」という発想になるのか俺には分からない
てきとーなプログラミング言語で
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:44hoge 3>&2 2>&1 1>&3
&1,&b,&3をそれぞれa,b,cと置き換えると
b=c, a=b, c=a;
だろ。評価順に考えればこうなる。簡単な話だ。
0873名無しさん@お腹いっぱい。
2010/10/08(金) 00:52:44c=b
b=a
a=c
の間違いでは?
代入の向きが違う
3>&2 は、fd3にfd2をdupする(3に2を代入する)わけでしょ
0874名無しさん@お腹いっぱい。
2010/10/08(金) 11:37:20逆だろ・・・
0875名無しさん@お腹いっぱい。
2010/10/08(金) 11:51:000876名無しさん@お腹いっぱい。
2010/10/08(金) 14:06:12馬鹿だろ・・・
0877名無しさん@お腹いっぱい。
2010/10/08(金) 14:38:12なるほど、評価順以前に
これすら理解していない人が話をひっかきまわしていたのか
0878名無しさん@お腹いっぱい。
2010/10/08(金) 19:21:10発想の元は同じなわけだし
0879名無しさん@お腹いっぱい。
2010/10/14(木) 16:51:17bashです
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:060882名無しさん@お腹いっぱい。
2010/10/14(木) 17:50:09そうです。
0883名無しさん@お腹いっぱい。
2010/10/14(木) 17:54:35あ、サブシェル問題だったんですね。よくわかりました。解決しました。
0885名無しさん@お腹いっぱい。
2010/10/14(木) 17:57:030886879
2010/10/14(木) 18:00:55解決しました
0887名無しさん@お腹いっぱい。
2010/10/14(木) 18:02:000888879
2010/10/14(木) 18:02:480889名無しさん@お腹いっぱい。
2010/10/15(金) 15:46:10function 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そのままで標準入力に対応してるけど。エスパー召喚?
0891名無しさん@お腹いっぱい。
2010/10/15(金) 16:24:19bash でしか動かん。
昔からの関数定義と比べて機能が強化されたわけでもないのに、
なんで bash はつまらない非互換を導入したがるんだか。
0892名無しさん@お腹いっぱい。
2010/10/15(金) 16:39:13zshでもkshでも動きますが。何言ってんだか。
0893名無しさん@お腹いっぱい。
2010/10/15(金) 17:29:28ifで正規表現を使った判別を行っていますが、複数条件の時はどうすれば良いのでしょうか?
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:03if [[ $i =? ^foo || $i =? ^bar ]]; then
0895名無しさん@お腹いっぱい。
2010/10/15(金) 17:49:04functionってわざわざ書くのが抵抗感あるかな。
函数って言うより、ただのサブルーチンだし。
0896名無しさん@お腹いっぱい。
2010/10/15(金) 17:57:07ありがとうございました。できました。
-oでなく、CやJavaで用いる||で良かったのですね。これなら覚え易いし、使い易いです。
=~と=?は同じでしょうか。これについては未だ不明なので調べてみます。
本当にありがとうございました。
0897名無しさん@お腹いっぱい。
2010/10/15(金) 18:00:280898名無しさん@お腹いっぱい。
2010/10/15(金) 18:02:25ありがとうございます。
なるほど、ではチルダで良いのですね。
重ね重ね本当にありがとうございました。
0899名無しさん@お腹いっぱい。
2010/10/15(金) 18:53:410900名無しさん@お腹いっぱい。
2010/10/18(月) 11:38:08そう思った根拠は何だ?
0901名無しさん@お腹いっぱい。
2010/10/18(月) 12:00:230902名無しさん@お腹いっぱい。
2010/10/18(月) 13:29:47発言の趣旨を問いたい
0903名無しさん@お腹いっぱい。
2010/10/24(日) 22:35:24実務でシェルスクリプトを書く皆さんはコメントって結構意識して書いてますか?
0904名無しさん@お腹いっぱい。
2010/10/24(日) 22:53:010905名無しさん@お腹いっぱい。
2010/10/25(月) 00:00:11やる気と関係者のレベル次第。
素のUnixなんかでVimが入っていない場合だと、めんどくさい上にミスしやすくなるし。
0906名無しさん@お腹いっぱい。
2010/10/25(月) 00:31:41シェルに限らず業務用ソースはコメントを意識して多めに入れる
シェルに限って言えば・・・ascii(英語)でコメント書くことかな
0907名無しさん@お腹いっぱい。
2010/10/25(月) 19:34:17外に出すシェルは当然難読化処理してから出すよな。
コメントなんて論外。難読化のためのオトリコメントはアリだけど。
0908名無しさん@お腹いっぱい。
2010/10/25(月) 19:39:310909名無しさん@お腹いっぱい。
2010/10/25(月) 19:43:50難読化ツール何使ってる?
perl用みたいにぐちゃぐちゃになる奴ある?
0910名無しさん@お腹いっぱい。
2010/10/25(月) 20:53:270911名無しさん@お腹いっぱい。
2010/10/25(月) 21:00:17昔何かで読んだ記憶があるが
実物を目にした事はない
0912名無しさん@お腹いっぱい。
2010/10/25(月) 21:25:190913名無しさん@お腹いっぱい。
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:10java scriptなんかだと、難読化しながらサイズもコンパクトになるという二重のメリットがあったりするが。
0915名無しさん@お腹いっぱい。
2010/10/29(金) 23:54:27HOGE="\* foo"
として、
echo $HOGE
* foo
と出て欲しいのですが、
\* foo
になっちゃいます。
ヒアドキュメントのパターンもためしてみましたがうまくいかず・・・。
0916名無しさん@お腹いっぱい。
2010/10/29(金) 23:57:200917名無しさん@お腹いっぱい。
2010/10/29(金) 23:58:19dashとbashでは期待通り。
0918916
2010/10/29(金) 23:59:350919名無しさん@お腹いっぱい。
2010/10/30(土) 00:26:15echo "$HOGE"
0920名無しさん@お腹いっぱい。
2010/10/30(土) 02:20:220921名無しさん@お腹いっぱい。
2010/10/30(土) 04:43:59thanx
ヒアの場合は
HOGE=`cat <<'EOF'
* foo
* bar
EOF`
echo "$HOGE"
でいいのね。助かりマスタ。
0922名無しさん@お腹いっぱい。
2010/10/30(土) 05:36:46bbb
ccc
というテキストがあるとしてcatして変数にx="aaa bbb ccc"と入れたいんだけどどうやればいいですか?
シェルはbusyboxのashです。
0923名無しさん@お腹いっぱい。
2010/10/30(土) 06:31:56x="$(cat foo.txt | tr '\n' ' ')"
0924名無しさん@お腹いっぱい。
2010/10/30(土) 07:48:54x=`cat hoge.txt`
x=`echo $x`
わざとダブルクォートを付けずに echo $x して xに代入しなおすのがポイント
>>923 はtrコマンドが無駄。
0925名無しさん@お腹いっぱい。
2010/10/30(土) 12:12:46あと、一旦 x に格納するだけ、無駄ですよね? > >>924
0926名無しさん@お腹いっぱい。
2010/10/30(土) 12:31:590927名無しさん@お腹いっぱい。
2010/10/30(土) 12:33:07もちろん >>924 の方が視認性がある
一旦 x に格納は無駄じゃない。
外部コマンドの trを起動するオーバーヘッドの方がよっぽど無駄。
元質問はbusybox環境だから、trのないbusyboxだったらそもそも実行できない。
どうしても一旦 x に格納したくなければ
x=$(echo $(cat hoge.txt))
とすれば良いが、この方が視認性が落ちる。
よって、>>924 が最適解。
0928923
2010/10/30(土) 12:54:58>>923の場合、最後に改行があるとcccの後にスペース入っちゃうし、改行が
\r\nだったら動かないとかあるんで、あんまりよくないとは思ってた。
0929名無しさん@お腹いっぱい。
2010/10/30(土) 14:27:46スクリプトを作れと頼まれればコメントを書くけど
何かの仕事を頼まれて、それ用にスクリプトを書いて
作ったときは書かない
0930名無しさん@お腹いっぱい。
2010/10/30(土) 14:37:470931名無しさん@お腹いっぱい。
2010/10/30(土) 18:07:30(検索に成功したら1とか)
0932名無しさん@お腹いっぱい。
2010/10/30(土) 18:12:030933名無しさん@お腹いっぱい。
2010/10/30(土) 18:54:04もっと深読みするんだ。
0934名無しさん@お腹いっぱい。
2010/10/30(土) 19:15:33ありがd
0935名無しさん@お腹いっぱい。
2010/11/01(月) 10:07:56hoge1
hoge2
hoge3
hoge4
hoge5
というデータがあり、これを読んで
hoge1 hoge2 hoge3 hoge4 hoge5
と1行で出力するshシェルスクリプトを教えてください。
0936名無しさん@お腹いっぱい。
2010/11/01(月) 10:16:290937名無しさん@お腹いっぱい。
2010/11/01(月) 10:54:01ちょっと斬新。
0938名無しさん@お腹いっぱい。
2010/11/01(月) 11:49:54while read x; do echo -n "$x "; done < filename | sed 's/ $//'
0939名無しさん@お腹いっぱい。
2010/11/01(月) 11:59:54じゃだめなん?
あ、最後の改行まで落ちるか。
0940名無しさん@お腹いっぱい。
2010/11/01(月) 12:11:010941名無しさん@お腹いっぱい。
2010/11/01(月) 12:13:070942名無しさん@お腹いっぱい。
2010/11/01(月) 21:22:510943923
2010/11/01(月) 23:22:06打ち間違えて ' が一つ足りませんでした。
>
が延々と出てCtrl+Cでも終了できません
お助けください orz
0944923
2010/11/01(月) 23:24:33と打ったら終了できました。
とりあえずスレ汚しすいません。。。
0945名無しさん@お腹いっぱい。
2010/11/01(月) 23:25:48Ctrl-Cは動いてるプロセスに 止まれよ! と通知するやつだから、
まだコマンド発行してない段階では通用しないわさ。
0946名無しさん@お腹いっぱい。
2010/11/01(月) 23:26:23だから 視認性(笑) がある >>924 の方を使えとあれほど、、
普通のシェルなら Ctrl+Cで終了できるよ。
クォートの途中を表す > プロンプトが出てるだけだから。
0947名無しさん@お腹いっぱい。
2010/11/01(月) 23:29:130948922
2010/11/01(月) 23:30:54>>923,924さんの方の両方で出来ました。
>>927さん詳しい解説と環境のご配慮までありがとうございます。
busybox-1.17.1で tr のアプレットまで入っているようです。
オプションは -c -d -s しかありませんでしたけど。
皆さん本当にありがとうございました。
またスレ汚しすいませんでした。
0949名無しさん@お腹いっぱい。
2010/11/01(月) 23:34:250950名無しさん@お腹いっぱい。
2010/11/02(火) 01:53:36od -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:220953名無しさん@お腹いっぱい。
2010/11/02(火) 08:48:16nとr逆じゃね?
CRLF = ^M^J なので、少なくとも改行が CRLFかLF だと分かっていれば
grep "^M$" < hoge.txt
でいいんじゃ?
(^MはCtrl押しながらmを打鍵)
0954名無しさん@お腹いっぱい。
2010/11/02(火) 08:59:21Ctrl+v Ctrl+m で入れる環境が多いと思うけど。
0955名無しさん@お腹いっぱい。
2010/11/02(火) 09:05:380957名無しさん@お腹いっぱい。
2010/11/03(水) 00:00:04ありがとうございます。
出来ました。
nとr逆ですね。
cat -v hoge
で見える改行コードの入力の仕方がわからなかったので助かりました。
しかし、grepって複数行の検索出来ないんですね。
0958名無しさん@お腹いっぱい。
2010/11/03(水) 00:02:35バックアップしたいディレクトリをフルパスで指定すると
tarのエラーで/を先頭に付けるな
と、怒られてしまったので
cdでバックアップ元のディレクトリに移動
↓
./でバックアップ元を指定して、バックアップ先へtar.gzで圧縮
という流れにしました
もっと良い書き方があるんだろうけどターミナル触るのが久々
過ぎてこんなぐらいしか思いつかなかった
もっと良い書き方はございますか
0959名無しさん@お腹いっぱい。
2010/11/03(水) 00:11:010960名無しさん@お腹いっぱい。
2010/11/03(水) 00:46:05manぐらい読めよ。
0961名無しさん@お腹いっぱい。
2010/11/03(水) 02:03:21最近はcdできるtarもいろいろあるけど。
0962名無しさん@お腹いっぱい。
2010/11/03(水) 09:21:440963名無しさん@お腹いっぱい。
2010/11/03(水) 12:08:56今更だが、 tar cf - -C /hoge/huga * とサブシェル内cdだと*の展開タイミング
が違うので、同じ投稿に並べて書いたのは不適切だったな。
0964名無しさん@お腹いっぱい。
2010/11/03(水) 19:05:58; じゃなくて && にすべし。; だと間違えて権限のないディレクトリに
cd しようとして失敗しても、カレントディレクトリのまま tar が実行されてしまうので、
場合によっては意図しないファイルを上書きして消すなんて事故が起きることがある。
というか、そういう事故を起こさないためにも -C を使ったほうがいい。
0965951
2010/11/05(金) 00:11:31確かにその方がいいですね
仕事でやってる時は事故を起こさないようにそうしてた気がします
ところでファイルサイズ違う件について心当たりある方いま(ry
その後もググって見たけど相変わらずわからずで
何回もスレ汚しスマソ
0966名無しさん@お腹いっぱい。
2010/11/05(金) 00:59:320967名無しさん@お腹いっぱい。
2010/11/05(金) 08:36:340968名無しさん@お腹いっぱい。
2010/11/05(金) 12:06:27何のファイルサイズがどう違うの?
レス数が950を超えています。1000を超えると書き込みができなくなります。