トップページ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/
0730名無しさん@お腹いっぱい。2014/05/20(火) 18:17:56.34
rubyがインストールされてないサーバは、少なくとも俺の身近には存在しない。
rubyが駄目だと言うのなら、次に考えるのはawkかsedだろ。常識的に考えて。
0731名無しさん@お腹いっぱい。2014/05/20(火) 18:33:31.84
ていうかperlを存命させるかどうかってのはそのOS、ディストリのコアな部分からそれを排除できるかの問題だろ。
rubyは入れる物を多少選べば排除できるが、perlへの依存を全て排除するのは無理ではないが結構面倒だろう。
0732名無しさん@お腹いっぱい。2014/05/20(火) 18:54:13.54
ここ何のスレだっけ。
0733名無しさん@お腹いっぱい。2014/05/20(火) 19:05:06.07
rubyとperlを罵倒しながら気分転換にシェルスクリプトの話をするスレ
0734名無しさん@お腹いっぱい。2014/05/20(火) 19:29:20.61
自分で環境作れないとこで、長々とワンライナー書くこともあまりない気がするけどなぁ。運用の人は書くのかな。
ビルトインとsedとawkで大抵こと足りるからな。perl使うのに多いのはライブラリ使いたい時とか。
でもそうするとpythonやrubyの方が最近のものがある気がする。pmとかまだ作られてるの?
0735名無しさん@お腹いっぱい。2014/05/21(水) 00:06:27.58
>>729
一行野郎と言えば「awkは書かねぇ、たった一行」だろ?
0736名無しさん@お腹いっぱい。2014/05/21(水) 03:32:28.76
うちのdebianにはperlとpythonは入ってるがphpとかrubyは入ってない
0737名無しさん@お腹いっぱい。2014/05/21(水) 05:00:52.02
Windowsですらtexと一緒にperl/awk/sed/grep辺りが住んでたりするな
0738名無しさん@お腹いっぱい。2014/05/21(水) 08:41:33.68
入ってないっていうか入れてないんだろ。
0739名無しさん@お腹いっぱい。2014/05/21(水) 08:47:53.28
>>730
rubyを入れなくても何にも困ってない rails?()
perlを入れてないとコンパイルできないものが結構ある(PostgreSQLとか)

ruby信者の視野狭窄は異常
0740名無しさん@お腹いっぱい。2014/05/21(水) 09:18:31.41
rubyで書く奴のおかげでrubyからpythonへの書き換えで飯が食えるとかなんとかw
0741名無しさん@お腹いっぱい。2014/05/21(水) 09:41:02.86
>>739
コンパイルの依存関係にperl入れるのは辞めてほしい
0742名無しさん@お腹いっぱい。2014/05/21(水) 10:01:39.33
>>741
autotoolsに依存するより全然まし
0743名無しさん@お腹いっぱい。2014/05/21(水) 10:02:56.58
やっぱxmkmfだよなw
0744名無しさん@お腹いっぱい。2014/05/21(水) 17:28:29.71
>>739>>741
コンパイルの依存関係にrubyやpythonが入るより少しはマシ
って言おうかと思ったけど自分の遭遇トラブルはperl依存モノの方が多かったorz

>>742
コンパイル省力化に高機能なツールや言語を使い出して、
今度はそっちの互換性問題が火を噴くとか本末転倒にもホドがある…

最小限のシェルスクリプトかMakefileで済む奴が一番気楽だわ
0745名無しさん@お腹いっぱい。2014/05/21(水) 17:39:42.30
> って言おうかと思ったけど自分の遭遇トラブルはperl依存モノの方が多かったorz
その分野ではrubyやpythonは使われてないからだろ。特にrubyは日本限定末端土方専用だから。
使われてなきゃトラブルには遭遇しない。当たり前だ。
0746名無しさん@お腹いっぱい。2014/05/21(水) 17:42:51.81
FreeBSDのperl依存地獄は凄いからな
perlのアップデートとかなったら阿鼻叫喚の渦
あと何かのプロジェクトで頑張ってperl依存をなくしたってニュースになったな

perlは撲滅すべき悪ではあるがまだ依存関係から取り除けてない害虫みたいなもんなんだろう
0747名無しさん@お腹いっぱい。2014/05/21(水) 18:01:29.51
>>743
お、懐かしいね。Canna じゃまだ使われているのかな?
0748名無しさん@お腹いっぱい。2014/05/21(水) 18:15:59.05
そういや Perl で one liner って使わなくなったな…
昔はこんなのを↓よくやってたけどね

$ perl -pi.bak -e 's:#!/usr/bin/perl:#!/usr/local/bin/perl:' *.pl

最近使ったのは…Run Length Encoding かな

$ echo '......' | perl -pe 's/(.)(\1+)/$1.(length($2)+1)/ge'

RLEって sed や awk, UNIX tools を組み合わせて one liner でできるのかな…
0749名無しさん@お腹いっぱい。2014/05/21(水) 18:35:56.58
>>746
お察しの通りFreeBSDだが、FreeBSDは脱GPL脱GCCの実績が有るし今後に期待?
0750名無しさん@お腹いっぱい。2014/05/21(水) 20:41:31.00
>>748
http://rosettacode.org/wiki/Run-length_encoding
ぐぐったらsed版とawk版があるな
つーかrun length encodingって必要になった状況ないな
0751名無しさん@お腹いっぱい。2014/05/22(木) 00:16:14.56
RELENG_5あたりでbaseからは脱Perlしてるじゃねえの
0752名無しさん@お腹いっぱい。2014/05/22(木) 09:09:18.24
確かに今では base に perl が含まれてはいませんが、実際に perl を入れずに
運用しているサーバを私は見たことがありません。
でも perl が入ってないサーバって、実は世の中には結構あるんですかね?
0753名無しさん@お腹いっぱい。2014/05/22(木) 09:30:02.07
>>752
じょ、冗談で書いてるんだよね?
0754名無しさん@お腹いっぱい。2014/05/22(木) 10:12:42.49
>>753
というと?
0755名無しさん@お腹いっぱい。2014/05/22(木) 12:16:17.56
perlなんて当然入れてない
0756名無しさん@お腹いっぱい。2014/05/22(木) 12:20:57.50
元からperlなんて入っていないし、要らない。
必要なら入れれば?な感じ。
0757名無しさん@お腹いっぱい。2014/05/22(木) 15:33:22.17
Debian wheezyの標準的なapt-lineで、各言語に依存するものの数を数えた。
その言語自身のセクションと、libsは除いてみた。
$ for l in perl python ruby ;do echo -n "$l ";aptitude search ~D$l\!~s$l\!~slibs|wc -l;done
perl 962
python 1603
ruby 204
0758名無しさん@お腹いっぱい。2014/05/22(木) 15:41:24.61
今日からperlやめてnode.jsに移行してみる
0759名無しさん@お腹いっぱい。2014/05/22(木) 21:37:53.41
>>758
それでタイプ量の多さに失望するんですね。
0760名無しさん@お腹いっぱい。2014/05/24(土) 11:07:22.49
シェルでテキスト処理の部分だけperlでやるのが一番無難だと思うけどなぁ。
sh系なら-e''の中に改行含めれるし。

最近はもう、awkをさけるようになったなぁ
なんで正規表現の互換性をなくしてしまったのか。
0761名無しさん@お腹いっぱい。2014/05/24(土) 11:56:11.33
>>742
autotoolsって、シェルスクリプトとm4とmakeで
できてるから、このスレ的には新参スクリプト言語よりは
歓迎なんじゃないかって気がするw
0762名無しさん@お腹いっぱい。2014/05/24(土) 21:11:49.14
「〜に依存する」だけならそれ入れれば済む話だが、
「auto」toolsはマニュアルで修正しないとコンパイル通らない場合が…
0763名無しさん@お腹いっぱい。2014/05/24(土) 21:55:46.18
修正マニュアルがあるならいいじゃないかw
0764名無しさん@お腹いっぱい。2014/05/25(日) 14:19:48.29
マニュアル=手作業 とマジレス
0765名無しさん@お腹いっぱい。2014/05/29(木) 00:34:01.91
FreeBSDが脱cshできればperlもしぼんでくと思う。だからまずしぼまない。
0766名無しさん@お腹いっぱい。2014/05/29(木) 17:22:41.57
いや、src.confでコンパイルしないようにするだけ。
もう、何年も前からcshは入ってないが何も不都合は生じてない
0767名無しさん@お腹いっぱい。2014/06/07(土) 16:19:13.77
数百万行のテキストをshのツールに食わせて実行結果を得る、なんてことをよくやるんだが、
プログレスバーを作って待ち時間のストレスを抑えようと思う
今何%進んでるかは実行行/全体行で簡単に分かるんだが、これを画面上に出力する時に、
単純に計算結果を出力するだけだと
 [05%]・・・・・
 [06%]・・・・・・
 [07%]・・・・・・・
という風に毎回改行されて表示されて画面が汚くなるのが嫌だ

つまり何が聞きたいかというと、既に出力された結果を書き換えるような仕組みはshで実現可能なのだろうか
分かりにくくてすまない
0768名無しさん@お腹いっぱい。2014/06/07(土) 16:20:12.71
>>767
^M
0769名無しさん@お腹いっぱい。2014/06/07(土) 16:26:43.02
^M のあと tput el しとくといいかも
0770名無しさん@お腹いっぱい。2014/06/07(土) 16:34:33.53
tputってFreeBSDで互換性ないんだよなぁ、、
0771名無しさん@お腹いっぱい。2014/06/07(土) 16:57:46.03
echo のオプションとか printf とかは?
0772名無しさん@お腹いっぱい。2014/06/07(土) 17:01:08.23
>>768-769
ありがとう。tputを初めて知ったが、勉強してみる
しかし^Mがわからん。何のことだ

>>771
echo -nで改行無し出力は出来るから、いわゆる伸びていく棒は再現出来た
が、すでに出力したn%のnを書き換えるような操作が出来ない
printfはそういうの出来るんだろうか?
0773名無しさん@お腹いっぱい。2014/06/07(土) 17:17:09.83
>>772
コントロール-Mを知らんのか? キャリッジリターンだぞ。カーソルは左端に戻る。
0774名無しさん@お腹いっぱい。2014/06/07(土) 17:23:46.19
マジかよ
いや^MがCtrl-Mなのは知ってたけどそんな効果あったのか
次会社いったら試してみる、ありがとう

ついでに調べてたら、某ブログでecho "\r\c"なるものを目撃した
これも同じ意味かな
0775名無しさん@お腹いっぱい。2014/06/07(土) 17:34:07.91
>>774
もしNetBSDならprogress(1)に逃げるって手もある
0776名無しさん@お腹いっぱい。2014/06/07(土) 17:47:05.14
echoはポータビリティに難があるのでprintfの方が良い
0777名無しさん@お腹いっぱい。2014/06/07(土) 17:49:02.97
printfもポータビリティに難があるが、、
0778名無しさん@お腹いっぱい。2014/06/07(土) 20:29:23.80
dialog --gauge もある
0779名無しさん@お腹いっぱい。2014/06/07(土) 20:46:07.95
>>770
FreeBSDがどうのというより、termcapとterminfoの違い。
0780名無しさん@お腹いっぱい。2014/06/07(土) 20:47:59.07
>>779
そんなことわかった上で言ってるんだがw
0781名無しさん@お腹いっぱい。2014/06/08(日) 00:08:18.41
rで行頭からかくか、エスケープシーケンスでいいんじないかな。
ただ、ログのこと考えると、ただ延びていくだけのプログレスで十分だと思うけどなー
0782名無しさん@お腹いっぱい。2014/06/08(日) 01:23:49.35
URL1=...
URL2=...
URL3=...

と定義して
for ((i=1;3>i;i++))
do
 処理
done

の形で $URL$i と書いても URL1 などに展開されないのだが
正しくはどう書けばよいのでしょうか?
0783名無しさん@お腹いっぱい。2014/06/08(日) 02:03:50.42
eval echo '$'URL$i

eval url='$'URL$i
echo $url
0784名無しさん@お腹いっぱい。2014/06/08(日) 02:38:49.86
配列にしちゃうとか。

declare -a URL
URL[1]=...
URL[2]=...
URL[3]=...

for ((i=1;4>i;i++))
do
 echo ${URL[$i]}
done
0785名無しさん@お腹いっぱい。2014/06/08(日) 02:48:13.36
>>767
数値とプログレスバーと両方あるといいね。rpm -ivh みたいに。
sun wsのブート時みたいに棒を回すのもなかなかいいよ
0786名無しさん@お腹いっぱい。2014/06/08(日) 02:58:19.85
i<3 にしよう
0787名無しさん@お腹いっぱい。2014/06/08(日) 03:04:42.61
シンタックスエラーでなかなか回答遅れて申し訳なかったです
とりあえず暫定的に下のforループでしのぎました。
数が多くなると保守性が終わるけど。

for i in $URL1 $URL2 $URL3
do
......
done


>>783,784,786
文字連結のための''を使った回避術、
declareを使った配列宣言、
いいアイデアをいただきました。ありがとうございます。
0788名無しさん@お腹いっぱい。2014/06/08(日) 07:08:45.79
棒回しいいなー
上書き方法会得したらそれも試してみよう
0789名無しさん@お腹いっぱい。2014/06/08(日) 07:47:05.10
while :; do
 for t in '|\r' '/\r' '-\r' '\\\r'; do
  echo -en "$t"
  sleep 0.1
 done
done
0790名無しさん@お腹いっぱい。2014/06/08(日) 16:28:53.32
何かと思ったら棒回しか
\\がうまくいきゃいいが
07917872014/06/08(日) 17:36:41.96
>>784
配列良いね
素晴らしく短くまとまった
保守性もばっちりだ
重ね重ね感謝申し上げる

URL=( \
#valiant
  http://m...
#watchSomething
  http://j...
#script
  http://b...
)

# download from URL, and add header
for ((i=0;i<3;i++))
do
 echo ${URL[i]}
done
0792名無しさん@お腹いっぱい。2014/06/08(日) 17:42:21.90
3から不変ならいいんだが、配列にするならこうしてみるのはどうか

for ((i=0; i<${#URL[*]}; i++))
do
 echo ${URL[i]}
done

手元に実行環境がなくて検証出来ないから間違ってたらスマン
0793名無しさん@お腹いっぱい。2014/06/08(日) 17:53:32.13
>>792
ありがとう。
httpで件数だけ埋め込む作業要らなくなった

${#配列名[*]}で取り出せるのか
こんな#が合ったなんて知らなかったよ
0794名無しさん@お腹いっぱい。2014/06/08(日) 21:41:28.47
テンポラリファイルの扱いについて訊きたい

一部のファイルをrmしてないバグがあるスクリプトを走らせてしまい/tmpに多数ファイルを残してしまった
このようなミスを抑える対策とかありますか
0795名無しさん@お腹いっぱい。2014/06/08(日) 21:45:16.18
>>794
入力、処理、出力、という流れを意識して、設計書を書き、
ポイントポイントで処理の目的に即したテスト項目を作って、
結果を他人が評価できるようにテストを実施することだよ
0796名無しさん@お腹いっぱい。2014/06/08(日) 22:51:32.33
>>794
シェルスクリプト一般だと、tmpfile(3)みたいにプログラムが終わると勝手に消える
ようにするのは難しいだろうね。頑張れば出来るかもしれないけど・・。

一時ファイルというと、とりあえずファイル名に$$を入れたりすることが多いけど、
そういうのを含めない(可能なら固定名にする)のが、バグがあっても
悲惨なこと(/tmpが枯渇するなど)にならない設計方法のひとつ。
もちろん可能な場合だけど
0797名無しさん@お腹いっぱい。2014/06/08(日) 23:43:54.83
>>794
オブジェクト指向で設計し、インスタンスの寿命が尽きる時にファイルが消去されてることを確認し、されていなければ破棄する。
サポートされていない言語だと例外時に忘れがちなので注意。
0798名無しさん@お腹いっぱい。2014/06/08(日) 23:53:29.64
開始時に mkdir /tmp/アプリ名-プロセス番号/ してそこに作業ファイルを置いて、終了時に
rm -f /tmp/アプリ名-プロセス番号 すれば良いだけでは?
trap 使えば SIGTERM とか SIGINT にも対応できるし、bash なら終了時にキックもできる。

複数インスタンスの稼働を想定しないなら >>796 の言うように名前固定して、既存ファイルが
ある場合にエラーでとまるようにするとかもアリかな。
0799名無しさん@お腹いっぱい。2014/06/09(月) 00:03:28.76
小手先の対応で何とかするよりも、ちゃんとテストする方がよかろうよ
0800>>7942014/06/09(月) 00:26:53.38
>>795-799
チェック漏れがこんなことになるとはなあ
/mntにはtempfsをマウントしていないから簡単には使い切れないのが幸いだった

tempfileとrmをループ外へ追い出してみるのと、こんな感じで一時ファイルの場所の移動を試してみます
export TMPDIR=$(mktemp -d)
trap "rm -rf $TMPDIR" EXIT

>>797
言葉足らずで申し訳ない。問題のスクリプはzshスクリプトです
0801名無しさん@お腹いっぱい。2014/06/09(月) 00:57:13.18
>>797はからかってるか、マジボケかのどっちかだろうよ
0802名無しさん@お腹いっぱい。2014/06/09(月) 02:38:45.23
trap "command" EXIT
なんて用法があったのか。やはりこのスレは勉強になる
0803名無しさん@お腹いっぱい。2014/06/09(月) 11:27:14.45
>>801
実装ミスであるなら、どんな仕組みを使っても同じ。
設計手法はそういったミスを抑えるためにもある。
そして設計ミスが生まれる。

おそらくは例外時だろうけど、具体的なバグを聞かないと実装による対処方法は確定しない。
0804名無しさん@お腹いっぱい。2014/06/09(月) 11:33:19.20
それより一時ファイルを作らない方法でシェルスクリプトを記述するのがいいよ。
パイプやコマンド置換でかなりのところまで行ける。
どうしても一時ファイルが要る場合でも、openしたまま先にrmしとくとかでかなり対処できる。
trap 'rm file' 0 とかで消すのはkill -9 された場合は無理だし。
0805名無しさん@お腹いっぱい。2014/06/09(月) 13:22:45.34
トラップ一家物語
0806名無しさん@お腹いっぱい。2014/06/09(月) 15:57:02.71
Cでオブジェクト指向っぽい事するのは例があるけど、
シェルスクリプトでやるのは労力に見合うのだろうか…
0807名無しさん@お腹いっぱい。2014/06/09(月) 16:03:28.20
Perlのblessされたスカラのリファレンスのようなもの?
0808名無しさん@お腹いっぱい。2014/06/09(月) 16:39:23.19
そもそも構造体がないからねえ
0809名無しさん@お腹いっぱい。2014/06/09(月) 20:29:57.19
そんなのより関数作るのが先だろ
0810名無しさん@お腹いっぱい。2014/06/09(月) 23:23:09.12
HEADER
AA(55)
AA(20)
FOOTER
となっているファイルを食わせて、
HEADER
AA(11)
AA(4)
FOOTER
を吐かせたい。
つまり()内の数値を5で割ったものを吐かせたいんだが、これをshでやるとしたらどういうやり方する?
試しにsed噛ませようと試みたけどあれ演算するのすごいめんどくさそうで
0811名無しさん@お腹いっぱい。2014/06/09(月) 23:39:14.15
つawk
0812名無しさん@お腹いっぱい。2014/06/09(月) 23:41:42.95
$ expr "AA(55)" : ".*(\([[:digit:]]\+\)).*"
55
$ echo $((55/5))
11
$
0813名無しさん@お腹いっぱい。2014/06/10(火) 00:06:17.61
IFS=
sed -e 's/\$/\\$/' -e 's!\(([0-9][0-9]*)\)!(\$((\1/5)))!g' | while read l; do eval echo "\"$l\"";done
0814名無しさん@お腹いっぱい。2014/06/10(火) 00:24:48.89
sedの中で$((\1/5))なんて出来るのか?
0815名無しさん@お腹いっぱい。2014/06/10(火) 00:55:00.72
出来ないね。でも>>813は要求仕様通りに動作する。
0816名無しさん@お腹いっぱい。2014/06/10(火) 01:23:49.76
$$(expr 式)
0817名無しさん@お腹いっぱい。2014/06/10(火) 09:08:48.05
>>814
sedにshスクリプトを書かせてるわけだね。
0818名無しさん@お腹いっぱい。2014/06/10(火) 10:03:19.34
今時の sh は bash か ksh93 が標準なのか…
0819名無しさん@お腹いっぱい。2014/06/10(火) 10:44:55.16
>>816
sed -e 's/\([$`]\)/\\\\\1/g' -e 's!\(([0-9][0-9]*)\)!(\$((\1/5)))!g' -e 's/^/"/'
-e 's/$/"/'|while read l; do eval echo "$l";done

>>818
$((expr))のこといってるならposix shellだよ
http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
08208182014/06/10(火) 12:11:58.44
>>819
Solaris8 や HP-UX10 あたりの sh は演算置換できなかった覚えがあるんだけど、
便利になったなあ…
0821名無しさん@お腹いっぱい。2014/06/10(火) 12:15:49.48
何に準拠してるかではなく、スクリプトを書かせてる発想が大事であって、自分の環境で動かなかったら書き換えればいいだけ。
08228102014/06/10(火) 12:29:01.86
おお……すごいな
自分の発想が貧困だったことを思い知らされる
ありがとう
0823名無しさん@お腹いっぱい。2014/06/10(火) 14:09:06.28
eval使うほどの案件じゃない
0824名無しさん@お腹いっぱい。2014/06/10(火) 14:28:20.32
威張るな
0825名無しさん@お腹いっぱい。2014/06/10(火) 14:32:11.80
eval使わずに、$((xx)) も使わずに:

while IFS='()' read a b; do
if [ "$b" ]; then
echo "$a(`expr $b / 5`)"
else
echo "$a"
fi
done
0826名無しさん@お腹いっぱい。2014/06/10(火) 14:53:54.80
>>825
AA(55) や AA(20) の行末に何か文字が入ってしまうとエラーになる
>>819 なら "AA(20) BB(100) CC(65)" とかになっていてもOK
0827名無しさん@お腹いっぱい。2014/06/10(火) 14:56:24.36
>>826
そんなことわかった上で、要求仕様だけ満たす最小限で書いているのだよ。
0828名無しさん@お腹いっぱい。2014/06/10(火) 14:58:01.83
悔しいのぅ〜悔しいのぅ〜
0829名無しさん@お腹いっぱい。2014/06/10(火) 15:05:19.71
>>826
>>819 は入力に " が1個とか(奇数個)含まれてるとエラーになるぞ。
>>825 ならOK
■ このスレッドは過去ログ倉庫に格納されています