トップページunix
987コメント278KB

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

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2012/11/15(木) 18:57:33.11
シェルスクリプトの総合スレです。
□お約束
・特記なき場合は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に逃げずにシェルスクリプトで処理するのが頭のいいやり方。
前スレ
シェルスクリプト総合 その20
http://toro.2ch.net/test/read.cgi/unix/1339083351/
0042名無しさん@お腹いっぱい。2012/12/06(木) 22:24:28.37
>>41
このように展開される

$a{_a,_b,_c}→$a_a $a_b $a_c
$a{,_a,_b,_c}→$a $a_a $a_b $a_c
${a}{,_a,_b,_c}→${a} ${a}_a ${a}_b ${a}_c
0043名無しさん@お腹いっぱい。2012/12/06(木) 22:32:45.24
>>42
ああ、よく分かりました。ありがとうございます。
0044名無しさん@お腹いっぱい。2012/12/06(木) 22:33:08.64
>>41
手元で動作を確認する限り

2$ は {} の展開を先にしてる
つまり $a_a $a_b $a_c としてから変数の処理
=> 何も出力されない

3$ も同様
$a $a_a $a_b $a_c としてから変数の処理
=> $a だけ定義されてるから foo が出力

どこかマニュアルに展開の優先順位があるかもしれないがそれは確認してない
0045442012/12/06(木) 22:34:57.60
リロードしてなかった(´・ω・`)
すまない...
0046名無しさん@お腹いっぱい。2012/12/07(金) 14:07:46.57
screen使いです。
bash_historyって何行ぐらいにしている?
直近のhistory | grep hoge | lessってするなら3桁の900行で十分だよね。
もうちょっと前のも検索したいなら4桁の9900行。 # 自分は余裕もってこれ。
9366$

メモリ食いそうだから、スクリプトを組んで今までの全部の履歴十数万行を検索するのも
超ひさしぶりのコマンド用途としてはありそう。その超ひさしぶりに使うコマンド用途なら
# とコメントをつけておくとちょっと使いやすいかも。
0047名無しさん@お腹いっぱい。2012/12/07(金) 14:16:03.49
好きにしろ。
0048名無しさん@お腹いっぱい。2012/12/07(金) 14:57:28.68
ヒストリーは何行にしてても
端末複数開いてたら消えちゃうし
いつ打ったかの時間情報ないし
あんまり意味がないよね
0049名無しさん@お腹いっぱい。2012/12/07(金) 15:29:36.16
>>48
> ヒストリーは何行にしてても
> 端末複数開いてたら消えちゃうし
自分の力量の視野の狭さだとちゃんとexitって閉じると残るよ。
> いつ打ったかの時間情報ないし
> あんまり意味がないよね
時間情報は環境変数の設定で秒数まで残るかな。秒数の小数点はスクリプトで工夫すれば
残せそうかな。そこまでの必要性がないからやっていないけど。
0050名無しさん@お腹いっぱい。2012/12/07(金) 15:43:25.01
シェルスクリプトでヒストリ残して何がうれしいの?
0051名無しさん@お腹いっぱい。2012/12/07(金) 17:11:43.25
シェルスクリプト内でhistory使う方法教えて。

#!/bin/sh
コマンド1
コマンド2
history

と書いて実行してもhistoryが何も表示されない><
0052名無しさん@お腹いっぱい。2012/12/07(金) 17:17:08.00
>>51
set -o history でどうかな。
0053名無しさん@お腹いっぱい。2012/12/07(金) 19:52:21.63
>>46
zsh使いなら死ぬまで履歴を残すもんだってばっちゃが言ってたから
50万行にしてる。
もちろん複数の端末起動してもちゃんとshare_historyされる設定。
0054名無しさん@お腹いっぱい。2012/12/07(金) 23:24:10.48
プログラミング初心者です。
以下のコードがシェルの文法的におかしい点を教えて下さい。
ex1はargvでファイル名を読み込む外部のC++プログラムです。
不足してる情報もあると思いますが、分かる範囲で教えていただけたら助かります。

#!/bin/sh

DIRx=$1
DIRy=$2

filesA=`ls $DIRx/*.data`
filesB=`ls $DIRy/*.data`
for x in $filesA;
for y in $filesB;

do
./ex1 $f $fi
done
0055名無しさん@お腹いっぱい。2012/12/07(金) 23:31:28.06
なんでそんな間違い方するのか意味不明
釣りっぽい
0056名無しさん@お腹いっぱい。2012/12/07(金) 23:39:25.77
すみません、釣りじゃないです。
ちょっと調べて、これでできたかもしれないです。
もし間違っていたら教えて頂けないでしょうか。
如何せんコンパイルはできるものの実行結果が合っているか確認する術が無いもので…

for x in $filesA;
do
for y in $filesB;
do
./ex1 $x $y
done
done
0057名無しさん@お腹いっぱい。2012/12/07(金) 23:51:12.55
質問者ではないのですが この for/do/done の構文
言語仕様策定の上で、do の存在はどうしても必要だったの?
改行かセミコロンでループブロックの区切りは付きますよね
もし無かったらアレができないよみたいな do の活用法なんてあるのでしょうか?
単に do/done なら覚え易いよね!程度だったら残念かも
0058名無しさん@お腹いっぱい。2012/12/08(土) 00:12:36.76
>>56
*.data で得るファイル名に空白がないのなら問題ない
空白があれば
IFS=$'\n'
が必要

文法はいい。というか文法以外のex1の意図がわからないけど
0059名無しさん@お腹いっぱい。2012/12/08(土) 01:40:05.03
>>58
ありがとうございます、空白はありません。
お陰様でなんとかできました、ありがとうございました。
ex1はただの実行ファイルで、名前に特に意味はありません。
0060名無しさん@お腹いっぱい。2012/12/08(土) 08:14:05.32
>>54,>>56
釣りとは思わないけど、やりたいことはなんとなくわかるけどケアレスミスが多すぎて
判読不可能。
>>57
どの力が働いて、今の構文なのかはわからない。おまじないってことでいいんじゃないのw

Unix創世期はほとんどがディスプレイなし、テレタイプ端末、スペック貧弱と想像できるから
テキストエディタvi, emacsは使えずに開発環境はラインエディタ。
創世期シェルを作った開発形態・志向も違うだろうし、for-do-doneを言うならcase-esac,
if-fiもどうなのってツッコミたくなるしなあ。その当時回文みたいなのが流行っていたの?
教育言語のPascalも律儀に{}だからね。
現在のemacsでksh, bashのfor文テンプレート使うとdo-doneってつくね。過剰に装飾している
だけかもしれないけど。
0061名無しさん@お腹いっぱい。2012/12/08(土) 09:21:06.89
>>60

ラクダ本(オライリーのPerlの本)の初版用語集によると、ある語の逆綴りを
採用するのはALGOL主義、だそうだが、elif(fileの逆綴りでもある)がない
理由として半ばジョークめいた書き方だったので話半分に。

# Pascalはbegin/endじゃ…
0062名無しさん@お腹いっぱい。2012/12/08(土) 14:39:25.53
>>60
born shellの作者がAlgolが好きだったから。
0063名無しさん@お腹いっぱい。2012/12/08(土) 16:02:40.46
骨?
0064名無しさん@お腹いっぱい。2012/12/08(土) 17:03:07.57
>>62-63
英語の成績悪かったらしい奴が2人いるみたいだが、突っ込んだら負け。
0065名無しさん@お腹いっぱい。2012/12/08(土) 22:04:44.58
?マークの意味が分からない奴がいるな・・・
0066名無しさん@お腹いっぱい。2012/12/08(土) 22:22:47.71
任意の一文字マッチって意味でしょ。それぐらい知ってるよ。
0067名無しさん@お腹いっぱい。2012/12/09(日) 10:42:10.50
シェルスレなんだから変数が未設定かどうかの確認って答えるべきだな
0068名無しさん@お腹いっぱい。2012/12/09(日) 10:43:37.85
シェルglobだから>>66で正しい。
0069名無しさん@お腹いっぱい。2012/12/09(日) 10:46:03.34
>>66
bo?rn?
0070名無しさん@お腹いっぱい。2012/12/09(日) 18:39:45.90
誰もシェルグロブなんて言ってないけどな
0071名無しさん@お腹いっぱい。2012/12/10(月) 09:34:25.06
>>67
どういう意味? ?で変数の何が分かるの?
0072名無しさん@お腹いっぱい。2012/12/10(月) 10:11:21.88
>>71
${hoge:?}
0073名無しさん@お腹いっぱい。2012/12/10(月) 13:52:17.02
${foo:+hello}
fooが nullかunset なら "", それ以外は "hello"

${foo+hello}
fooが unsetなら "", それ以外は "hello"

前者は man bash にて仕様が
${parameter:+word}
Use Alternate Value. If parameter is null or unset, nothing is
substituted, otherwise the expansion of word is substituted.
のように確認できたのですが、後者が見あたりません
どの辺を見れば載っているでしょうか? 或いは man レベルでは載っていない仕様でしょうか?
0074名無しさん@お腹いっぱい。2012/12/10(月) 14:13:26.18
>>73
あ、それちょうど今週のレポートで学生に課したネタなんで、
知ってる人も答をここには書かないでね。(偶然は恐ろしい)
0075名無しさん@お腹いっぱい。2012/12/10(月) 14:36:02.61
うち学生じゃないんですが・・・
ならせめてレポート提出日が過ぎたら教えてください
0076名無しさん@お腹いっぱい。2012/12/10(月) 14:38:03.86
さっきのは null か unset の判別はどうやったらいいのか調べていたら見つけた小技です
0077名無しさん@お腹いっぱい。2012/12/10(月) 14:57:36.75
>>73
http://linuxjm.sourceforge.jp/html/GNU_bash/man1/bash.1.html#lbBB
> コロンを省略した場合には設定されているかどうかのみを調べます。
これじゃね。
0078名無しさん@お腹いっぱい。2012/12/10(月) 17:47:50.38
>>77
ありがとうございます。それですね。
辿ってみたら man bash でも該当する箇所がありました。
0079名無しさん@お腹いっぱい。2012/12/10(月) 17:55:03.11
そりゃman bashの和訳だもの。
0080名無しさん@お腹いっぱい。2012/12/10(月) 18:53:49.37
わらかすなよ
0081名無しさん@お腹いっぱい。2012/12/13(木) 04:02:30.30
>>79
意味不明
0082名無しさん@お腹いっぱい。2012/12/13(木) 11:02:31.60
>>81
もともとbashのmanは英語で書かれていたんだよ
0083名無しさん@お腹いっぱい。2012/12/13(木) 23:00:47.57
わかる方がいたら教えてください。

引数で入力した値で、設定ファイル(~/test.conf)の置換文字列(%replace%)を置換することを考えています。

replace_str=%replace%
input=$1
sed -e "s/${replace_str}/${input}/" ~/test.conf

上記のようなことを考えていますが、入力値に /(スラッシュ)があると、sedコマンドがエラーになってしまい、うまく置換ができません。
入力値に /(スラッシュ)がある場合でも正しく置換する方法はありますか?

また、/(スラッシュ)以外でもNGになってしまう文字はありますか?
その文字も正しく置換することは可能でしょうか。
0084名無しさん@お腹いっぱい。2012/12/13(木) 23:11:09.68
>>83
入力値に絶対入らない文字はある?
あれば / のかわりにそれを使う。

sed -e "s,${replace_str},${input}," ~/test.conf

みたいに。
0085名無しさん@お腹いっぱい。2012/12/13(木) 23:14:17.61
そんな文字を仮定できないなら、
$1中の / を \/ に置換してからinputに入れるしかないかな。
この置換がまたやっかいかもだが。
0086名無しさん@お腹いっぱい。2012/12/13(木) 23:29:11.48
replace_str=${replace_str//\//\\/}
たぶんこれでいけるでしょう
0087名無しさん@お腹いっぱい。2012/12/14(金) 12:41:31.89
>>83
\や&も特殊な意味を持つと思うよ
俺なら、sedを使わざるをえないなら$inputに使える文字に制限を付けるかな
0088名無しさん@お腹いっぱい。2012/12/14(金) 12:52:19.32
sed 's/%replace%/_replace_/g' | m4 -D_replace_="$input"
0089名無しさん@お腹いっぱい。2012/12/14(金) 20:54:59.74
>>87
相手がWebの先の人間だったりするとそういう制限は難しいんじゃ
0090名無しさん@お腹いっぱい。2013/01/03(木) 00:00:22.31
シェルスクリプトでHex値を書き換える事は出来ますか?

バイナリファイルAのHex値
00100000のようなものを01100000のように書き換えたいです。
駄目元で、
cat A | sed -

e 's/00100000/01100000/' > A
のようにやってみましたがダメでした。
0091名無しさん@お腹いっぱい。2013/01/03(木) 00:02:32.45
>>90
きみのsedは16進数値をかけるsedなのかい?
0092名無しさん@お腹いっぱい。2013/01/03(木) 00:23:12.33
>>91
やっぱり無理なんでしょうか。…
0093名無しさん@お腹いっぱい。2013/01/03(木) 01:02:55.97
bcかawkでも使っとけ
0094名無しさん@お腹いっぱい。2013/01/04(金) 01:11:51.48
シェルスクリプト バイナリファイル でぐぐると最初になかなか面白そうなのが出てきた
個人的にはperl使うのが楽だと思うけど
0095名無しさん@お腹いっぱい。2013/01/04(金) 10:22:05.55
>>94
これ?
http://www.flat7th.org/~keizo/wiki/?page=%2B+%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%A7%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA%E6%93%8D%E4%BD%9C
0096名無しさん@お腹いっぱい。2013/01/05(土) 23:39:03.74
FreeBSDの/bin/shのソースって単体配布されてないのん?
0097名無しさん@お腹いっぱい。2013/01/06(日) 00:05:05.98
これを見る限り、それさえ既に魔改造版でしかないみたいw

ttp://www.in-ulm.de/~mascheck/various/ash/ash.png
0098名無しさん@お腹いっぱい。2013/01/06(日) 00:25:20.45
shのソースV7のでおなかいっぱい
0099名無しさん@お腹いっぱい。2013/01/06(日) 04:34:44.00
>>96
基本的に全部まとめて配布なのが
BSDの良い所の一つだよ。

でも単体取得する方法もある。
0100名無しさん@お腹いっぱい。2013/01/06(日) 09:24:06.28
その方法とは!?
0101名無しさん@お腹いっぱい。2013/01/06(日) 10:44:45.32
>>92
xxdで変換したの編集してからxxdで復元
0102名無しさん@お腹いっぱい。2013/01/07(月) 00:09:45.57
>>100
svnからゲッツ、じゃね
http://svn.freebsd.org/base/head/bin/sh/
0103名無しさん@お腹いっぱい。2013/01/07(月) 13:31:44.54
>>91
うちのsedは書ける
0104名無しさん@お腹いっぱい。2013/01/07(月) 22:27:46.05
>>102
僕のケータイでも読めた。
でもインストールがわからない。
みんなどーやってインストールしてるの?
僕のケータイリナックスってやつらしいけど
客がシェル使えるよーになってないから
これインストールしたら客もシェル使えるんだ。
でもインストールがわからない。
0105名無しさん@お腹いっぱい。2013/01/08(火) 11:07:30.16
>>104
configureしてmake install
0106名無しさん@お腹いっぱい。2013/01/08(火) 15:17:53.67
でもライブラリに分割されるとか魔改造されてて、あっさりとコンパイルできないのが常。
baseシステムに組み込まれてるのは取り出せないと思った方がいい。
0107名無しさん@お腹いっぱい。2013/01/08(火) 16:40:37.49
MINIX(86)のシェルを移植するのだ!
0108名無しさん@お腹いっぱい。2013/01/08(火) 18:03:08.60
フリーなの無いでしょ。
0109名無しさん@お腹いっぱい。2013/01/12(土) 21:11:02.86
2> /dev/null

2>&-
って書くとまずいことあるの?

おしえて先生!
0110名無しさん@お腹いっぱい。2013/01/12(土) 22:41:52.39
>>106
ほとんど手が入っていないであろう net2 のソース持ってくるってのは?
0111名無しさん@お腹いっぱい。2013/01/13(日) 14:15:52.18
>>109
writeの失敗を検出するようなコードが書いてあると困る
0112名無しさん@お腹いっぱい。2013/01/13(日) 14:36:10.22
どこにですか?
0113名無しさん@お腹いっぱい。2013/01/13(日) 15:03:28.37
#include <unistd.h>
int main(){
if(write(2,"hello",5) == -1){
return 1;
}
return 0;
}
こんな感じかな。
0114名無しさん@お腹いっぱい。2013/01/19(土) 01:07:47.55
>>109 &amp;- ってどういう構文なの? htmlとか?
>>111 エラーを返さない方が困ります
0115名無しさん@お腹いっぱい。2013/01/19(土) 02:20:17.72
仕様変更した2chと、
それに対応してない専ブラ使うやつと、
&amp;が何かも知らずにつっこむやつ
0116名無しさん@お腹いっぱい。2013/01/19(土) 02:32:56.96
と、ドヤ顔で解説する奴と

ニヤニヤしながら傍観してるオレ。
0117名無しさん@お腹いっぱい。2013/01/19(土) 10:36:37.19
あー &ー なのか
失礼
0118名無しさん@お腹いっぱい。2013/01/19(土) 18:28:47.20
初心者だから使えるコマンドがlsとかなのは共通事項。
たまにネットがおかしいと聞くと言われて打った
ifconfigは command not found になったりするんだよね。
0119名無しさん@お腹いっぱい。2013/01/19(土) 18:39:44.08
ifconfigは/usr/sbinにあったりするからな。
0120名無しさん@お腹いっぱい。2013/01/19(土) 18:50:09.03
解決策を聞いてるんじゃないよ。(というか知ってるし)
そうそうと共感してくれればいいのに。
面倒臭い人ね。
0121名無しさん@お腹いっぱい。2013/01/19(土) 21:26:02.44
そういう大事なコマンドは/sbinだろ。
0122名無しさん@お腹いっぱい。2013/01/20(日) 00:53:25.44
どこにシェルスクリプト要素があるんだ?
0123名無しさん@お腹いっぱい。2013/01/20(日) 02:42:53.88
>>120
誰でも知ってるような事を書いて
共感しろとは、勘違いも甚だしい
0124名無しさん@お腹いっぱい。2013/01/20(日) 03:42:08.87
さすがに生まれたての赤ん坊は知らねぇだろ
0125名無しさん@お腹いっぱい。2013/01/20(日) 05:26:07.60
赤ん坊が無知を装うのは大昔からの通例だろ
0126名無しさん@お腹いっぱい。2013/01/20(日) 05:38:37.73
会話できない以上知ってるかどうか確認する手段がないからな。
0127名無しさん@お腹いっぱい。2013/01/20(日) 10:43:48.19
くだらない質問ですが、
次のシェルスクリプトで★マークに入る方法があれば教えてください。
ARG0="$0"
while [ -h "$ARG0" ]; do
ls=`ls -ld "$ARG0"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
  ★
ARG0="$link"
else
ARG0="`dirname $ARG0`/$link"
fi
done

処理時代はシンボリックリンクの実体を辿る処理だという事は調べて、
なんとか分かったんですが、★の処理にはいる条件がどうしても分かりません。
別に入らなくてもいいのですが、気になってしまって・・・
0128名無しさん@お腹いっぱい。2013/01/20(日) 10:50:31.37
絶対パスへのリンク、じゃないの?
0129名無しさん@お腹いっぱい。2013/01/20(日) 10:54:20.46
>>127
解答を聞いてるんじゃないよ。
そうそう、こういう構文だと条件がわかりにくいよねぇー、
って共感してくれればいいんだけど。
0130名無しさん@お腹いっぱい。2013/01/20(日) 11:06:43.97
ってかreadlinkを自分で分かりにくく書いてみたってことでいいの?
01311272013/01/20(日) 11:12:54.89
>>128
ありがとうございます。
絶対パスで調べて、リンクを作りなおしたら通りました。
01321272013/01/20(日) 11:25:51.23
>>130
Linuxを使い始めたばかりで、
とりあえず適当なソフトをWebを見ながらインストールしていました。
その中でTomcatというソフトをインストールするのに、
シェルスクリプトの設置が必要と書かれており、そのサンプルが記載されていました。
しかし、サンプルの意味が全く分からなくて、そのまま使っていいのかも分からず
一から調べている最中でした。
0133名無しさん@お腹いっぱい。2013/01/20(日) 13:47:00.29
>>130
http://svn.apache.org/repos/asf/commons/proper/daemon/tags/COMMONS_DAEMON_1_0_7/src/samples/Tomcat7.sh
の事だな。特定の環境にしか存在しないreadlinkは使いたくなかったんだろ。
素人は黙ってなよ。
0134名無しさん@お腹いっぱい。2013/01/20(日) 14:49:14.74
リテラシ高いな
感心感心
0135名無しさん@お腹いっぱい2013/01/23(水) 14:41:17.73
もし、Aのディレクト内が空だったら、○○しなさい

の一番簡単なスクリプトは?
0136名無しさん@お腹いっぱい。2013/01/23(水) 14:56:34.29
find A -empty | fgrep -x A >/dev/null && ○○
0137名無しさん@お腹いっぱい。2013/01/23(水) 15:51:12.07
解答を聞いてるんじゃないよ。
そうそう、ディレクトリが空かどうかの判断って簡単にできないよねぇー
って共感してくれればいいんだけど。
0138名無しさん@お腹いっぱい。2013/01/23(水) 16:51:23.23
簡単にできるけど、回答知りたくないらしいから黙っておこう。
0139名無しさん@お腹いっぱい。2013/01/23(水) 17:03:26.94
コピペやん
0140名無しさん@お腹いっぱい。2013/01/23(水) 19:43:01.34
>>137
さぁ、お前のハードリンクを数えろ
0141名無しさん@お腹いっぱい。2013/01/23(水) 20:37:43.99
それだと内部のディレクトリ数しかわかんねえよ
■ このスレッドは過去ログ倉庫に格納されています