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

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

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2013/11/01(金) 07:58:50.52
シェルスクリプトの総合スレです。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashまたはdashなので特に注意。
 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でそれらしい単語による簡単な検索もできます。
・シェルで使えるワイルドカード等は正規表現ではありません。
 正規表現の話題はスレ違い(正規表現スレへ)
・シェルスクリプトのことをシェルってゆーな
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 awkまたはperlの方が適した処理にはそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
□回答者への注意事項:
・シェルスクリプトでの処理方法を質問しているのに、よくわからずに
 「そういうのはperl使いましょう」と回答するのはやめましょう。
 安易にperlに逃げずにシェルスクリプトで処理するのが頭のいいやり方。
前スレ
シェルスクリプト総合 その21
http://toro.2ch.net/test/read.cgi/unix/1352973453/
0180名無しさん@お腹いっぱい。2014/01/30(木) 20:24:02.53
許されないほうがなんかきもちいい。
0181名無しさん@お腹いっぱい。2014/01/30(木) 22:10:02.56
hoge="(株)ほげほげの売上は%1です。"
の%1をsedで置換したいのですが、(でエラーとなってしまいます。
特殊記号の()を読み飛ばして置換するにはどうすればよいですか?
0182名無しさん@お腹いっぱい。2014/01/30(木) 22:15:21.86
>>181
" " ではなく ' ' でくくるといい
0183名無しさん@お腹いっぱい。2014/01/31(金) 10:14:18.23
>>179
入れられるのならもう入れてるだろう。
0184名無しさん@お腹いっぱい。2014/01/31(金) 16:11:13.16
一生に一度くらいは入れてみたいものである。
0185名無しさん@お腹いっぱい。2014/02/03(月) 21:48:36.77
シェルスクリプトにてSQLの結果をメール送信するプログラムを作ろうと思います。
以下のようにやると$resultの結果が取れないのですが、どのようにしたらよいでしょうか?

sendMail() {
from=$1
to=$2
inputEncoding="utf-8"
outputEncoding="iso-2022-jp"
subjectHead="=?${outputEncoding}?B?"
subjectBody="`echo "$3" | iconv -f $inputEncoding -t $outputEncoding | base64 | tr -d '\n'`"
subjectTail="?="
subject="$subjectHead$subjectBody$subjectTail"
contents="`echo -e $4 | iconv -f $inputEncoding -t $outputEncoding`"
echo "$contents" | mail -s "$subject" "$to" -- -f "$from"
return $?
}
PSQL=`echo -e "\
〜〜〜SQL文〜〜〜
`

from="from@example.com"
to="to@example.com"
subject="件名を入力"
contents="SQLの結果"

result = echo "$PSQL" | psql -U hogehoge
contents=”結果です"
sendMail "$from" "$to" "$subject" "$contents$result"
0186名無しさん@お腹いっぱい。2014/02/03(月) 23:03:00.25
>>185

> result = echo "$PSQL" | psql -U hogehoge
result =$( echo "$PSQL" | psql -U hogehoge)
01871852014/02/04(火) 13:38:46.35
>>186
ありがとうございます
しかし、それだと改行がされないんですよね

A 152
B 585
C 209

と出したいところが

A 152B 585C 209

のようになってしまいます
0188名無しさん@お腹いっぱい。2014/02/04(火) 15:50:22.05
>>187
こんな感じ?もっといい方法ないのかな

echo "$PSQL" | psql -U hogehoge | while read line;do
result="$result\n$line"
done
0189名無しさん@お腹いっぱい。2014/02/04(火) 16:03:23.99
シェルでやるよりperlか何かでやる方が楽そう。
0190名無しさん@お腹いっぱい。2014/02/04(火) 16:49:38.80
>>187
規制くらってたわ。
改行を保持したいのなら、引数でわたすのではなくsendMailの標準入力に渡したほうが楽だろ。
echo "$PSQL" | psql -U hogehoge | "$from" "$to" "$subject" "$contents"
にして、sendMailのmailコマンドを
{echo "$contents" ; cat - } | mail -s "$subject" "$to" -- -f "$from"
のようにして呼べばいい
01911852014/02/04(火) 21:26:43.93
ありがとうございました!
0192名無しさん@お腹いっぱい。2014/02/08(土) 01:47:24.71
シェルでやれる範囲を超える場合はperlって人多いみたいけど、python派が少ないのは何でなの?
世の中的には最近やたらとpython流行ってるじゃないですか
0193名無しさん@お腹いっぱい。2014/02/08(土) 02:01:25.65
シェルスクリプトって one linerで書いてテストしながら組み合わせてく
ってよくやるけど、pythonは多くの構文が改行を要求するので、ふだんと
違う改行なしの書き方使うことに
なって違和感があるとか?

まあクオートの中に改行入れられるから、そうするって手もあるんだけど、
シェルによっては編集が不便になるし。
0194名無しさん@お腹いっぱい。2014/02/08(土) 02:25:02.21
echo $(( $RANDOM 55555 ))で55555までの乱数が出せますが、
55500から55555までと規制したい場合はどのようにすればいいのでしょうか?
0195名無しさん@お腹いっぱい。2014/02/08(土) 03:30:05.65
echo $(( (RANDOM % 56) + 55500 ))
0196名無しさん@お腹いっぱい。2014/02/08(土) 03:33:17.60
なるほど、そんなやり方があったんですね
参考になりました
0197名無しさん@お腹いっぱい。2014/02/08(土) 07:52:07.56
>>192
pythonは正規表現の使い勝手が良くないのとワンライナー書くのが実質的に無理
01981892014/02/08(土) 11:22:11.44
perl以外でやっても別にいいよ。
だから「perlか何か」と書いている。
01991892014/02/08(土) 11:28:02.40
perl使う人が多いのは
歴史が古いってのと他に乗り換える理由がないってだけじゃないかね。
ワンライナーにこだわる必要はないし、
いきなりpythonスクリプトのファイル書き始めても別にいいんじゃね。
好きな言語で好きなように書けばいい。
0200名無しさん@お腹いっぱい。2014/02/08(土) 15:19:08.22
>>196
それ自力で思いつかないとすると、相当センス悪いよ
0201名無しさん@お腹いっぱい。2014/02/08(土) 15:51:57.61
$RANDOMってたかだか 0〜32767 の値しかとらないから、
% 56 とかで剰余とったら値が小さい方に偏るから一様乱数にならないよ。
% 64 とか、2^n で剰余とった上で、値がはみ出した場合は再試行する方がいい。
0202名無しさん@お腹いっぱい。2014/02/08(土) 16:04:25.61
おおおおそういうことだったのか俺のバカ野郎!
横からだけど、ありがとう201さん!
0203名無しさん@お腹いっぱい。2014/02/08(土) 20:12:06.32
>>201
俺は言ってることがわからんけどw
コードでいうとどういう事?
0204名無しさん@お腹いっぱい。2014/02/08(土) 20:32:31.53
>>203
while (((i = RANDOM % 64) >= 56)); do :; done; echo $((i + 55500))
0205名無しさん@お腹いっぱい。2014/02/08(土) 20:58:46.89
>>192
デフォで入ってないから
0206名無しさん@お腹いっぱい。2014/02/08(土) 21:21:03.42
>>204
じゃぁ今思い付いたけど、ポート番号なんかのように数が大きい場合はどうするの?
49152–65535が自由に使えるけど、以下の場合は{$NUM}はどうするの?

while (((i = RANDOM % {$NUM}) >= 16384)); do :; done; echo $((i + 49152))

16384は2^nだけど、となるとi = RANDOM % 16384のままでいいの?
0207名無しさん@お腹いっぱい。2014/02/08(土) 21:22:59.32
というか、
echo $(( (RANDOM % 16384) + 49152 ))
のままでいいと言うことになるのかな?
0208名無しさん@お腹いっぱい。2014/02/08(土) 21:50:12.57
そういうことでしょ
2^nなら一様乱数になるんだから
0209名無しさん@お腹いっぱい。2014/02/08(土) 22:09:57.81
シェルスクリプトで実行したコマンド結果の標準出力、標準エラーをログファイルに出力するにはどうすればよいですか?

command > log.log

とひとつづつ書かないとだめなのでしょうか。
0210名無しさん@お腹いっぱい。2014/02/08(土) 22:15:11.27
#!/bin/bash
exec 1> log.txt
exec 2>&1

echo hoge
echo fuga >&2

ファイルにも標準出力にも出したい時は
exec 1> >(tee log.txt)
0211名無しさん@お腹いっぱい。2014/02/09(日) 16:46:34.97
>>209
スクリプト内のコマンド実行結果すべての標準出力/標準エラー出力を
まとめて同じログに送っていいなら、スクリプトの結果をリダイレクトすればよろし。
$ script.sh > log.log 2>&1

細かく制御したいなら、>>210 がよろし。
0212名無しさん@お腹いっぱい。2014/02/11(火) 11:30:01.58
>exec 1> log.txt
>exec 2>&1
なんで2行に分ける? basherは頭が悪いな
0213名無しさん@お腹いっぱい。2014/02/11(火) 18:09:26.52
exec 1> log.txt; exec 2>&1
こうか?
0214名無しさん@お腹いっぱい。2014/02/11(火) 18:14:28.58
xec >log.txt 2>&1

これかね 引数の順番を逆にすると駄目
0215名無しさん@お腹いっぱい。2014/02/12(水) 01:12:42.76
basherとかひとくくりにされてもな。
0216名無しさん@お腹いっぱい。2014/02/12(水) 01:20:04.91
バッシャー板前
0217名無しさん@お腹いっぱい。2014/02/12(水) 06:08:29.88
シェラー同士仲良くしろよ
0218名無しさん@お腹いっぱい。2014/02/12(水) 07:25:04.97
ゼットエスエッシャー
0219名無しさん@お腹いっぱい。2014/02/12(水) 08:43:11.54
今日も元気にシェルでワンタイマーしましょう
0220名無しさん@お腹いっぱい。2014/02/12(水) 16:58:41.44
>>215
> #!/bin/bash
こういうおバカはひとくくりでかまわない
0221名無しさん@お腹いっぱい。2014/02/12(水) 17:30:14.30
>>220
>>210 の最終行で named pipeの文法使ってるから #!/bin/bashにする必要がある。
#!/bin/sh で起動すると(たとえ実体はbashでも) sh互換モードになって named pipeの文法がエラーになる。
0222名無しさん@お腹いっぱい。2014/02/12(水) 18:31:03.25
>>221
bash固有機能は使うなよ
ということを言いたいのでは?
0223名無しさん@お腹いっぱい。2014/02/12(水) 18:46:49.62
>>222
使ってもいいじゃん、と言いたいのでは。
0224名無しさん@お腹いっぱい。2014/02/12(水) 19:07:56.04
tcsher涙目

・・・きっともう、シェルスクリプトはshやbashで書くtcshユーザも肩身が狭いんだろうな・・・
0225名無しさん@お腹いっぱい。2014/02/12(水) 20:22:10.38
zsherも忘れないで
0226名無しさん@お腹いっぱい。2014/02/12(水) 20:26:12.20
fisherさんかっこいい
0227名無しさん@お腹いっぱい。2014/02/12(水) 21:03:28.97
てっきり#!/usr/bin/env bashって書けって話しかと思ってた
0228名無しさん@お腹いっぱい。2014/02/12(水) 21:51:15.94
tcsh使う奴死ねと言われてからもう10年はたつだろ
もはやtcshユーザなんてどうしようもない偏執狂しか居ないはずだが
0229名無しさん@お腹いっぱい。2014/02/12(水) 22:03:29.03
HP-UXとかAIXとかはcsh標準らしいが
絶対使いたくないわ
0230名無しさん@お腹いっぱい。2014/02/12(水) 22:10:04.50
>>228
ホントスンマセン。by tcshユーザー

スクリプトは勿論Bourneシェルで書くんだけどねえ。
0231名無しさん@お腹いっぱい。2014/02/12(水) 22:10:16.14
そもそもHP-UXとかAIXとかいまさら使いたくない。
0232名無しさん@お腹いっぱい。2014/02/12(水) 22:16:18.78
>>230
それならいいんじゃね。
スクリプトのスレなんだから。
0233名無しさん@お腹いっぱい。2014/02/12(水) 22:26:25.01
>>232
あんがと。

企業で稀に見かけるcshスクリプト書きって、偏執狂というより
単なる物知らずって気がするよ。
bash登場以前、newcshとかあった頃は、対話的シェルはcsh系が
主流で、よく分かってない人の中には、なんとなくスクリプトもcshで
書くって人がいた(俺はその頃からスクリプトはBourneシェルだったけど)。
で、その頃に書かれたスクリプトを秘伝のたれみたいに直し直し
使ってるのを2000年頃に見て驚いたことがある。
俺のまわりでは、そういうのもさすがに滅んだけど。
0234名無しさん@お腹いっぱい。2014/02/12(水) 22:39:05.82
>>233
企業とか大学とかでもまだ見るよ、代々cshスクリプトをなおすところ。
基本 csh しかわからない人しかいないから sh に移行できない/しても指導できる人が居ない。
02352242014/02/12(水) 23:00:07.35
>>230
同じく
つってもプロンプトを移植するのが面倒でtcsh使ってるだけのニワカだけど・・・
0236名無しさん@お腹いっぱい。2014/02/12(水) 23:13:14.98
俺も2000年ごろにcshスクリプトに遭遇したな
ログインシェルもcsh系だった気がする
今となってはcshしかわからない人なんていないでしょ
わざわざコストをかけて書き直すほどのものじゃないって

そういやFreeBSD鯖のログインシェルはtcshのままにしてるな
デフォルトから変更するほどシェルに思い入れが無いだけかも
0237名無しさん@お腹いっぱい。2014/02/13(木) 00:09:22.64
bashのスクリプトを標準出力に吐き出すスクリプトを作ったのですが、この結果を一時ファイルに保存せずに
そのまま実行する方法があったら教えてください。
吐き出すスクリプトは具体的にはffmpegを複数行実行するものです。
bash -s とかやってみたのですが、うまくいきませんでした。
0238名無しさん@お腹いっぱい。2014/02/13(木) 03:59:27.39
>>237
echo ls | bash -s
とかで動くけど? (この場合は -s は省略可)
0239名無しさん@お腹いっぱい。2014/02/13(木) 07:46:40.27
>>221
>>>210 の最終行で named pipeの文法使ってるから #!/bin/bashにする必要がある。
「named pipeの文法」ってなんだよ
これだからbasherは… w
0240名無しさん@お腹いっぱい。2014/02/13(木) 08:29:17.43
>>237
/dev/nullにリダイレクトしては駄目なの?
0241名無しさん@お腹いっぱい。2014/02/13(木) 11:03:48.37
>>237
eval `echo ls`
02422372014/02/13(木) 12:55:37.44
>>238
そのやり方ですと、1行目で実行したffmpegが2行目以降を
キー入力として受け取ってしまうようなんです。。。
一度リダイレクトでファイルに出して、
bash tmp.sh
みたいにすれば問題なく逐次実行されます。
よく分かってないのですが、標準入力とttyの関係とかでしょうか
0243名無しさん@お腹いっぱい。2014/02/13(木) 13:17:07.98
>>242
ffmpeg </dev/tty
みたいにして、キー入力を端末に強制する方法と、
bash <(スクリプト)
みたいにして標準入力を使わずに済ます手がある。

だが、最初にキー入力の問題だと、ちゃんと書くように!w
02442372014/02/13(木) 14:38:09.52
>>243
どちらの方法も完全にうまくいきました、ありがとうございました!
後者のやり方がなぜうまくいくのかまだピンときていませんが、
いろいろ調べてみようと思います。
あと最初からキチンと書かなくてすみませんでした
0245名無しさん@お腹いっぱい。2014/02/13(木) 16:42:41.00
>>244
プロセス置換でググってみな
02462372014/02/13(木) 17:03:46.98
>>245
なるほど、こういう機能ってzshにある感じはしていたのですが、
bashにもあるんですね!
bashの ( ) はサブシェルだと思っていました…
0247名無しさん@お腹いっぱい。2014/02/13(木) 22:47:07.79
確かにzshにしかない機能と思ってたのがbashにあって驚くことあるな
少しずつ入れてんのかね
0248名無しさん@お腹いっぱい。2014/02/13(木) 22:49:59.70
入ってるね。
個人的には {1..30}が入ったのは地味に大きい。
それでもzsh使ってるけど。
0249名無しさん@お腹いっぱい。2014/02/13(木) 23:12:09.87
ヒストリの共有(share_history)が bash にも欲しい
0250名無しさん@お腹いっぱい。2014/02/13(木) 23:16:17.55
日々使うインタラクティブシェルとしてはzshが良いけど
バッチ処理させるスクリプトとしてならbashの方が使いやすい
というかzshは機能多すぎドキュメント多すぎで訳ワカメ
0251名無しさん@お腹いっぱい。2014/02/13(木) 23:39:34.45
スクリプトでもzshにしてる
どの機能がbashがサポートしてるか調べるのめんどい
0252名無しさん@お腹いっぱい。2014/02/14(金) 00:11:56.32
zshは.zshrc等をてんこ盛りにしてると、zshスクリプトが読み込みに超長時間かかる
かといって #!/bin/zsh -f にするとめちゃ使いづらいし・・・痛し痒し
0253名無しさん@お腹いっぱい。2014/02/14(金) 03:53:13.33
zshはバグ多い。

#!/bin/zsh
echo hoge >file1 >file2 >/dev/stdout

↑これだけで固まるw
0254名無しさん@お腹いっぱい。2014/02/14(金) 07:49:53.20
zshでスクリプト書くぐらいならperlでいいじゃんと思う
0255名無しさん@お腹いっぱい。2014/02/14(金) 07:55:46.01
>>249
PROMPT_COMMANDを仕込むことで実現してる人はいるよ。
http://iandeth.dyndns.org/mt/ian/archives/000651.html
でも標準機能としてほしいのは同意。
0256名無しさん@お腹いっぱい。2014/02/14(金) 10:23:51.87
>>138
ConnectBot、メモリ食い杉だ。他のシェル端末の方がいい。
0257名無しさん@お腹いっぱい。2014/02/14(金) 12:03:01.25
>>253
それバグじゃなくね。
0258名無しさん@お腹いっぱい。2014/02/14(金) 14:58:36.75
どうみてもバグだった
0259名無しさん@お腹いっぱい。2014/02/14(金) 15:23:01.77
>>256
オススメってある?
0260名無しさん@お腹いっぱい。2014/02/14(金) 23:52:33.86
>>253
何これ誰か解説して
0261名無しさん@お腹いっぱい。2014/02/15(土) 00:24:21.36
社史編纂室くんの出番や
0262名無しさん@お腹いっぱい。2014/02/17(月) 00:17:17.98
編纂の「纂」の字書ける人どんくらいいるだろう
0263名無しさん@お腹いっぱい。2014/02/17(月) 16:13:15.32
chassisのスペルと発音ちゃんと覚えてる人どんくらいいるだろう
0264名無しさん@お腹いっぱい。2014/02/17(月) 20:52:24.81
chassis hen sun shits
0265名無しさん@お腹いっぱい。2014/02/19(水) 16:43:38.09
初めてbashでスクリプト組んでるんですが、
. ./hoge.sh fuga.txt
みたいに引数渡して起動してるシェルを、引数変えて再起動するにはどうすればいいですか?
シェル内で
. ./hoge.sh $fuga
みたいに変数いれたらダメで、
. ./hoge.sh fuga2.txt
みたいに指定したら行けます。
0266名無しさん@お腹いっぱい。2014/02/19(水) 17:15:31.06
なんでsourceするの? ちょっと間違うと無限sourceループになるよ。
0267名無しさん@お腹いっぱい。2014/02/19(水) 17:18:00.48
>>265
その $fuga というのがスクリプト起動時にはまだ値がないんだろ? それなら駄目。
hoge.sh の中で fugaに値が代入されるとしても、それを起動時に指定することはできない。
0268名無しさん@お腹いっぱい。2014/02/19(水) 17:29:23.50
>>266
同じ構成の画面を、設定ファイルを指定して使い回すためです

>>267
ありがとうございます。
テキストにでも書き出して、そこから読み直してみます。
0269名無しさん@お腹いっぱい。2014/02/19(水) 17:49:40.79
>>267
だから、なぜ普通に起動せずにsourceで実行するのかを聞いてるんだが。
0270名無しさん@お腹いっぱい。2014/02/19(水) 18:00:57.53
>>268
init.dとかのスクリプト見て真似てみたら。
関数にして呼び出す。
0271名無しさん@お腹いっぱい。2014/02/19(水) 22:59:42.02
普通に出来るけど

$ cat hoge.sh
echo "hoge.sh is called with $1"
if [ "$1" = "fuga.txt" ] ; then
fuga="fuga2.txt"
. ./hoge.sh $fuga
fi

$ . ./hoge.sh fuga.txt
hoge.sh is called with fuga.txt
hoge.sh is called with fuga2.txt
02722652014/02/20(木) 09:12:57.78
みなさんありがとうございます。

どうやら変数の入れ方の様です。

fuga.txtに
trans_2=fuga2.txt
があって、

read input_key #ここで2を入力
eval input_trans='$trans_'input_key
echo $input_trans

これで
fuga2.txt
と出力されるのですが、
. ./hoge.sh $input_trans
とすると、引数を読まない感じです。
直前に
$input_trans=”fuga2.txt”
といれると動きます。

端末から直接書き込めないので、スマホで打ってるので、
読みにくくて申し訳ないです。
0273名無しさん@お腹いっぱい。2014/02/20(木) 11:48:12.75
なんでman見ないんだ?
. にはオプショナル引数は渡せない。無視される。

>>271
basherは「普通に」と言うな
02742652014/02/20(木) 13:03:57.32
>>273
なるほど。ありがとうございます。

manはききませんでした。
cygwinなので、インストールをスキップされてるのかもしれないです。
0275名無しさん@お腹いっぱい。2014/02/20(木) 14:55:50.29
>fuga.txtに
>trans_2=fuga2.txt
>があって、

もしかしてfuga.txtもsourceする?
そこに原因がある気がする
0276名無しさん@お腹いっぱい。2014/02/20(木) 19:07:54.76
>>273
でも、今は「普通=bash」だから仕方ないですよね・・・
0277名無しさん@お腹いっぱい。2014/02/20(木) 19:23:08.95
ログインシェルとシェルスクリプトシェルを混同すんな
ログインシェルならtcshユーザだってそこそこ居るんだぞ
0278名無しさん@お腹いっぱい。2014/02/20(木) 19:40:30.63
さすがに今はいないよ
0279名無しさん@お腹いっぱい。2014/02/20(木) 20:02:25.81
そもそもtcshがまだ存在するということに驚くというか
動いているところを見たことはない
■ このスレッドは過去ログ倉庫に格納されています