【貝】第1回シェル講座【殻】

このエントリーをはてなブックマークに追加
624名無しさん@お腹いっぱい。
#! /bin/sh

ftp -nv ***** <<EOF
user user
hash
bin
get ****
EOF

上のシェルでゲットの部分を引数で渡された回数だけ実行するには
どうすればよいでしょうか?
EOF〜EOFの間にはループ分とか記述できないので困っています・・
ヒアドキュメントを使わなければいいだけの話では。
目的がよくわからんが
wget とか curl を使った方がよいのでは。
here document のところをプログラムで生成すればいいんじゃ?
echo 嵐 マンセー
630名無しさん@お腹いっぱい。:03/11/10 11:31
hoge.txt に

fuga = foo

という行があるとしますよね.

シェルスクリプトでシェル変数 $FUGA に,
この foo を設定してやるにはどうしたらいいのですか?
FUGA=`awk '{ print $3 }' hoge.txt`
>>630
eval $(echo 'g/^\([^ ][^ ]*\) *= *\([^ ][^ ]*\)$/s//\U\1\e=\2;/p' | ex - hoge.txt)
FUGA=`awk '$1 ~ /fuga/ { print $3 }' hoge.txt`
>>633
FUGA=hoge
635ナミ:03/11/13 10:57
ある実行ファイルにパスが通っているかどうかで
if 文で処理を分けたいんですけどどうすればいいのですか?

例えば, awk にパスが通ってるかどうかで分岐させるには?
>>635
sh 系なら type か?
637名無しさん@お腹いっぱい。:03/11/13 14:11
シェルスクリプトの中で,
ユーザ定義函数を使おうとして,
以下のように書きました

#!/bin/bash
question 'Hello World!!'

function question()
{
echo $1
}

ところが,「question なんか知らない」というエラーが出ました

何が悪いんでしょう?
638ヽ(´ー`)ノ:03/11/13 14:17
>>637
先に定義しておかないと使えないヲカン

function question()
{
echo $1
}

question 'Hello World!!'
関数を定義するときに
function を使うなんて初めて知った・・・

hoge()
{
hage $@
}

が正式な文法だとばかり思ってた・・・(恥
>>639 bash拡張じゃない?
>>640
調べてみたらfunctionを使うのはbashの拡張みたいですね。
やっぱりなるべく使わないでおこ。
>>641
ほんとに?
POSIX標準(1003.2)で、そういう形式もOKって決まってなかったっけ?
643名無しさん@お腹いっぱい。:03/11/17 12:13
シェルスクリプトから他のシェルスクリプトファイルを
include することはできます?
もしできるなら,どうやってやるんですか?
>>643
.
>>644
ディスプレイの汚れかとおもった・・・
646名無しさん@お腹いっぱい。:03/11/20 10:28
$ bash hoge.sh *

としたら,現行ディレクトリの
すべてのファイルの先頭行に,

//hoge

という行が追加されるようなシェルスクリプトはどう書くの?
#!/bin/sh
tmpfile="/tmp/hoge.$$"

for d in "$@" ; do
if [ -f "$d" -a -w "$d" ]; then
echo "//hoge" > $tmpfile
cat "$d" >> $tmpfile
cp $tmpfile "$d"
fi
done
648646:03/11/20 11:16
>>647

すばらしい!
649ごんた:03/11/20 15:22
shシェルスクリプトにて、
PATH_INFO="/home/test/image/abc.jpg"
であるとき、
eval `echo $PATH_INFO | sed /^(.*\/)([a-z]+)\.([a-z]+)$/{
$Path=$1
$FileName=$2
$Ext=$3
}`
としたら、根本的に違うらしい。
 どうしたらパターンマッチさせて、任意の文字列を取り出せるのでしょう
 
>>649
正規表現は悪くないんだけど perl っぽかったり、
変数を使えない sed で代入しようとしてたりですごいことになってるねw
さらには sed の置換処理部分をクオートしてないんで
シェルが解釈しようとしてエラーになるはず。

Path=`dirname $PATH_INFO`
FileName=`basename $PATH_INFO | sed 's/\(.*\)\..*/\1/'`
Ext=`basename $PATH_INFO | sed 's/.*\.\(.*\)/\1/'`
651ごんた:03/11/20 17:12
なるほど、置換した結果を拾う。

ただ、
test.sh________________
#!/bin/sh
Path=`dirname $PATH_INFO`
FileName=`basename $PATH_INFO | sed 's/\(.*\)\..*/\1/'`
Ext=`basename $PATH_INFO | sed 's/.*\.\(.*\)/\1/'`
echo 'Content-type: text/plain'
echo
echo \PATH_INFO = $PATH_INFO
echo \$Path = $Path
echo \$FileName = $FileName
echo \$Ext = $Ext
exit 0
では、実行してみても
bash$ sh ./test.sh
$Path =
$FileName =
$Ext =
bash$
652ごんた:03/11/20 17:13
それで、

・・・値が無い。それで

PATH_INFO="/img/src/eee.jpg"
Ext=`echo $PATH_INFO | sed 's/.*\.\(.*\)/\1/'`
Path=`echo $PATH_INFO | sed 's/\(.*\)\/[^\/]*\..*/\1/'`
FileName=`echo $PATH_INFO | sed 's/.*\/\([^/]*\)\..*/\1/'`
echo 'Content-type: text/plain'
echo
echo \PATH_INFO = $PATH_INFO
echo \$Path = $Path
echo \$FileName = $FileName
echo \$Ext = $Ext
exit 0
としてみた。
 なんとなくカッコ悪いような・・
>>652
test.sh呼ぶ前にPATH_INFOをexportしてるのかと問い詰めたいところだが、

#拡張子が必ず存在するなら、このほうが見やすいかも。
export Ext
Path=`dirname "$PATH_INFO"`
Ext=`basename "$PATH_INFO" | sed 's/.*\.//'`
FileName=`basename "$PATH_INFO" $Ext`

#evalだとこんな感じ?途中にスペースがあるとダメだけど。
set `echo $PATH_INFO | sed 's|^\(.*\)/\([^/]*\)\.\([^.]\)|\1 \2 \3|'`
Path=$1
FileName=$2
Ext=$3

#拡張子が存在するかどうかもアヤシイんだったら、こんなのとか。
Path=`dirname "$PATH_INFO"`
FileName=`basename "$PATH_INFO" | sed 's/\.[^.]*$//'`
Ext=`basename "$PATH_INFO" | sed "s/^$FileName\.//"`
もっと気楽にいこーよ!
awk -F/ '{ print $NF }' とか
awk -F. '{ print $NF }' とか

LIST="a b c"
HOGE="hoge."
から、
"hoge.a hoge.b hoge.c"を生成するにはどうしたらいいのかな。
for i in $LIST
do
RESULT="$RESULT $HOGE$i"
done
>>655
% export LIST="a b c"
% export FOO="foo."
% for i in `echo $LIST`; do echo $FOO$i; done
foo.a
foo.b
foo.c

do echo を do touch にする。
>>656
なるほど。${bar#word}系の類いに気がいってて思い付かなかったよ。

>>657
例示した文字列が紛らわしくてスマソ。
659名無しさん@お腹いっぱい。 :03/11/27 16:42
unix(solaris)で使っていたシェルがRedHatでつかえません。
どうしてでしょうか?
>>659
shellってなんだか理解してからがんばれ
661名無しさん@お腹いっぱい。:03/12/02 20:03
/usr/bin/env の挙動が理解できません.例えば,

#!/usr/bin/env /usr/bin/clisp
(format t "Hello, world.~%")

このようなファイルに chmod u+x して実行するとします.
1 行目が上のときにはうまく動作しますが,可搬性を考えて
1 行目 を #!/usr/bin/env -i PATH=/usr/bin clisp とすると

env: オプションが違います --
詳しくは `env --help' を実行して下さい.

と言われてしまい,#!/usr/bin/env PATH=/usr/bin clisp とすると
メッセージが出ないまま固まります.
可搬性のある書き方で正しく動作させるには,どうしたらいいのでしょうか?
>>661
それは俺も悩んだことがある。
どうやら引数がまとめられて1つになるらしい。
#!/bin/ls -l -a
/bin/ls: オプションが違います --
この場合ls '-l -a'となってしまう。

#!/usr/bin/env clisp
というか、普通はこうじゃないか?
663661:03/12/02 21:25
>>662
うちのマシンではそれでいいのですが,
CGI として使いたいところが,PATH=/usr/bin という素敵なシステムなんです.
ますます #!/usr/bin/env clisp でいいと思うのだが
>>663
#!/usr/bin/clisp
でいいじゃないか。
666661:03/12/02 22:34
説明不足スマソ.

>>664-665
非常に残念なことに,その某大学のシステムでは (大学名を foo とします),
PATH=/bin:/usr/bin:/usr/foo/bin:/usr/foo/gnu/bin:
/usr/foo/pub/bin:/usr/foo/pub/lib/teTeX/bin:/usr/ucb:
/usr/foo/X11/bin:/usr/foo/bin/isc:/usr/ccs/bin の他にも,
/opt 以下に多数の bin を加えてはじめて実用になるシステムなのであります.

#! の行は,なるべく書き換えたくないものです.
どうか一人前の env 使いにしてください.お願いします m(_ _)m
667661:03/12/02 22:36
連続スマソ./usr/foo/pub/bin/clisp にあるので PATH の追加無しには使えません.
#! の後には実行ファイルと引数1つまでしか書けないと思った方が良い。
特に可搬性を求める場合は。

PATH を変えたいといった場合は、シェルスクリプトにするとかしか無いと思う。
#!/bin/sh
PATH=/bin:/usr/bin/:...
clisp filename
669661:03/12/02 23:00
>>668
どうもありがとう.悲しい index.cgi になりそうです...
引数は「ひきすう」と読むのだぞ(w
.htaccess で SetEnv PATH ... とすればいいのでは?
(´-`).。o(…Solaris か…あればイイ OS だ…)

>>671
.htaccess 禁じられてそうなヲカン。

>>670
他にどう読む
>>670
俺は昔「いんすう」と読んでいた。
ちなみに返値のことを「へんち」とも読んでいた。うはは
675661:03/12/06 15:45
>>671-672
.htaccess は使えますが,cgiwrap は必ずしないと実行できないんです.
そのせいか,cgi で呼ばれると .htaccess を無視しているようです.
>>674
俺は「いんかず」「かえち」だった
                \ │ /
                 / ̄\   / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
               ─( ゚ ∀ ゚ )< かえちかえち!
                 \_/   \_________
                / │ \
                    ∩ ∧ ∧  / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄\∩ ∧ ∧ \( ゚∀゚)< いんかずいんかずいんかず!
いんかず〜〜〜!  >( ゚∀゚ )/ |    / \__________
________/ |    〈 |   |
              / /\_」 / /\」
               ̄     / /
引き吸うも返り血も漏れには適当な命名とは思えない。
意味的、日本語的に。一体どんなDQNの思いつきだよ..
さらに
>>670
みたいなタイプが助長していて最悪だな。
・食わせ値
・戻り値(現行)
に汁
不特定多数の数なんぢゃないの?<引数の数
>>678
引いて、吸って、返り血なんだよ。日本語的には
筋が通ってるがな
682名無しさん@お腹いっぱい。:03/12/10 20:00
シェルスクリプトの中で,
例えば,$SQL というシェル変数に,
ある sql 文の文字列をもっているとします.

この sql を(シェルスクリプトの中で)
psql を使って,database という名前のデータベースに
かましてやるにはどうしたらいいのでしょうか?
>682
echo $SQL | psql database
684676:03/12/10 22:58
>>677
喜んでもらえて光栄ざます。
685名無しさん@お腹いっぱい。:03/12/11 11:38
バイナリの置換はをする方法はありますか?

具体的には,あるテキストファイルの
0x0D というバイトをすべて削除したいんですけど
>>685
tr か?
687名無しさん@お腹いっぱい。:03/12/11 15:14
ありがとうございます

cat hoge.txt | tr -d '\015'

で解決しました.
>>687
catいらんやろ。trの入力をredirectすりゃ済むやん。
もれ、grep を使うときでさえも

cat hoge.txt | grep fuga

とかやるよん。経験的にこのように書いておくと、あとで修正・改造が楽なのだ。
>>689 たとえばどのように楽なの?
>>690
>>689 じゃないけど、自分の経験では、

% cat hoge.txt | grep fuga
% cat hoge.txt | grep -i fuga
% cat hoge.txt | grep -i "fuga|foo"
% cat hoge.txt | grep -i "fuga\|foo"

みたいに続けて入力する時に、
カーソル移動が少なくて済む。

まぁ、カーソルを一字づつ移動させんな、とか
正規表現くらい一発で書け、とか
「% <hoge.txt grep fuga」でいいじゃん、とか
言われれば、そのとおりだが。
>>691
$ grep fuga < hoge.txt
$ grep -i fuga < hoge.txt
$ grep -i "fuga|foo" < hoge.txt
$ grep -i "fuga\|foo" < hoge.txt
とやってもカーソル移動は同じですが。
もしかしてDOSシェルかなんか使ってる?
>>692
% head hoge.txt
% ^head^cat
% cat hoge.txt | grep fuga
% cat hoge.txt | grep -i fuga

とか、いきなり grep じゃない事は多い(例がいけてないな・・・)。
grep | sort | uniq みたいな多段パイプを
いろんなファイルに対して繰り返しやるときは、
最初を grep RE hoge.txt とか grep RE fuga.txt とかにするよりも
cat hoge | grep RE にしておいた方がラク。

そんなことよりも、grep | awk とやってる奴をどうにかしてほしい。
たしかに。
まず最初にファイルの中身を確認してから、grep 操作をするじゃん。

$ less hoge.log
$ less hoge.log | grep fuga
$ less hoge.log | grep fuga | cut -f 1 -d " " | sort | uniq -c

とか。
less からパイプで渡すのはなんかヤだな。
grep | awkってなんかまずいの?
grep pattern | awk '{action}'
awk '/pattern/{action}'

意味ないでしょ。
>>694
> cat hoge | grep RE にしておいた方がラク。
はあ。なにが楽なんかよくわからない。
シェルに何を使っているかとかにもよるだろうし。
viモードなのかemacsモードなのかにもよるだろうしなあ。
標準入力と標準出力でインターフェースを共通化しておくことのメリットが分からないなんて
>>699はUnixをあまり使わない人間だと思う。
vi モード使ってるやつっているの? 一々 "^[" 押すのは面倒じゃないかな。
エディタは vi 愛用してるけど、コマンドラインのキーバインドは emacs 風だな。
好きなように使えばいいさ。
そうだね、スナフキン。
vi キーバインドは、コマンドが長くなった時にちょと便利かなと思ってたよ。
ところで emacs キーバインドで、ワード単位でジャンプする方法無いかな?
ごみん。M-f, M-b ででけた。
>>701
は〜い。俺tcshでもzshでもviのキーバインドだよ。
f,t,で目標の文字まで飛べたりとか、ct}なんかで括弧のなかを全書き換えとか
便利だと思うんだけどな。
でもさすがにhistoryは入力モードの^P,^Nに割り当ててます。
#でも厳密にキー叩く回数数えたら、
#emacsバインドに比べて少なくはないなと思いますが慣れました。
>>700
それがコマンドラインの編集にも適用できると思っているのって
なんだかあれですね
つかシェルあんまし使ってないんじゃないかな.>700は。
知識はあるんだけど現実に応用できないよくいるUnix馬鹿。
一番ダサい。
699 == 706 == 707 は具体的な例を挙げてみてよ。UNIX 使った事が
あるならだけど。
>>708
すんませんが日本語しゃべってください。
何の具体的な例ですか?
699=706=707=709はLinuxを使いはじめて1年目の厨房なんだから。反抗期なんだよ。
>>709
取りあえず cat を噛まさない方がキー入力回数が減るところからだな。
712699 692:03/12/13 18:21
>>711
とりあえず 'cat ' 、'|' という最初にいれる文字列分はキー入力が少ないですね。

本人かどうかわからんけど(つうかそもそも2ちゃんねるではそれを推測したりする
のはナンセンスだが)

>>700 とか >>708 ってなんか空疎なんだよな。

>>691からはじまる薀蓄は「どっちが楽か」という現実の使用に直結した
話なんですが、

>>700
「標準入力と標準出力でインターフェースを共通化しておくことのメリット」
(これ自体もかなり意味不明だが)

これが今の話題にどう関係しているのかが示されてないんだよ。
もしよければ ***具体的*** にシェルでのコマンドライン編集とどう関係するのか
教えてくれ。

俺が書いたUnix馬鹿ってのは「インターフェイスが共通化できる」とか
「直交性が…」という言葉と辞書的意味は知っているが実際にそれがどう便利
なのかが分かっていないやつのことで>>700はまさによい標本なわけだす。

以上、必死な反抗期のオコチャマの反論でちた。
ksh でかつ vi モードだと
ファイル名が最後にあると Esc + _ が使えて便利だね。
>>712
煽りはスルー。
もれは>>695を書いた人間だけど、これってひとつの答えになっていないかな?
>>713
はいはいご苦労さん。
内容に一言も言及できないってことは理解できてないってことですな。

2ちゃんねるとはどういうところなのか勉強しなおしてください。
ちなみに君のレスは「禿同」と書いたのとほぼ等価ですw
>>715
なってない
>>712
それがスレの流れを無視して、煽り文句書いていた理由ですか?
>>717
どこらへんが答えになってないかな?
あおる訳じゃないが、をれ的には
cat hoge.txt | grep foo
cat -n hoge.txt | grep foo
とかよく切り替えるからってのがある・・・
>>720 の例はあんまりよくないかも。。。
grep にも -n オプションがあるぞ、とか突込まれそうだし。
>>720
そういう時はこうしてる。cat ではあまり使わないけど。

% cat foo.txt | grep bar
% ^ ^ -n
cat -n foo.txt | grep bar
レスがあると思ったらこれかよ・・・
おまいは何を期待してるんだ?
>>718

どの辺が「スレの流れを無視して、煽り文句書いていた理由」にみえまっか?
指摘は具体的によろしく。
>>712
> >>700
> 「標準入力と標準出力でインターフェースを共通化しておくことのメリット」
> (これ自体もかなり意味不明だが)

単に「UNIXにはパイプがあって便利だね」といってるようにしか読めないよな。
コマンドラインの操作性を語るときは、どのシェル使っての話か書いたほうがよいね。
(なんか粘着されてるっぽいな・・・。)
あるスクリプト x があって、x の中身は下のような感じです。

#!/bin/sh
コマンドA
コマンドB
コマンドC
exit 0

スクリプト x を、

$ cat hoge.txt | ./x

としたとき、このスクリプトへの標準入力をCに食べさせたいのですが、
どうすればよいでしょうか。

AとBが標準入力を食べないプログラムならCが食べてくれるようですが、
AとBが標準入力を食べるプログラムだとCに回ってきませぬ。
>>729
コマンドA,B,Cをリストにして

for i in $list ; do
cat hoge | $i
done

でいけないかな・・・。
>>730
レスありがとうございまする。
標準入力から入るのは無限長のデータの可能性もあるので

% uuencode /dev/urandom hoge | ./x

のような感じで実行しても動作して欲しいなぁ、と考えています。
>>728
言い訳探しをしても有益ではないと思うよ
#!/bin/sh
コマンドA < /dev/null
コマンドB < /dev/null
コマンドC
exit 0

じゃあかんの?
>>732
まともな返事をしても、応えを期待出来る相手じゃないじゃん。
何時まで続けるの?
 | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
 | >>734      |
 |  馬鹿は放置!  l
 |_________|
   ∧∧ ||
   ( ゚д゚) ||
   /  づΦ
そだね。スマソ。
>>734
また言い訳ですな。正直になったほうがよいとおもいまつよ。
>>735
翻訳:「理解できないものにはフタをしよう」
質問です。

「標準入力と標準出力でインターフェースを共通化しておくことのメリット」
とはどういう意味ですか?
>>739
いきなり宿題丸投げみたいなこと聞かれても(以下略
シェルのコマンドを
$ date
のようにするのではなく
$ { date ; }
のように { ... ; } で挟むとどういった違いがあるのですか?
コマンドリストを一括りにする。その例では違いはでないね
>>742
thx
なぞがとけました。
「標準入力と標準出力でインターフェースを共通化しておくことのメリット」
というのを先日聞いたのですが、Unix関係の文書とか書籍とかでも見聞きした
ことがないセンテンスなんですが、これってUnixのどの特徴を指して言ってるの
でしょうか?
宿題の丸投げ禁止。
先生の意図していることを汲み取って回答してあげないと単位はもらえないよ(w
747モナBERT:03/12/21 02:52
シェルスクリプトが一番多く書かれて技巧の研究が進んだ時代は
perl出現以前の1980年代だと思うけど、当時は>>689,691のような
方式を見た記憶ないし、>>700のような主張もされなかったはず。
(スクリプト内での話ね。他人のコマンドライン操作はよく見てない。)

もちろん、当時はtcshのコマンドライン編集なんてなかったとか、
大きく状況が変化したから、21世紀の今は今なりでいいよ。

個人的には、>>700のメリットはやっぱわからん。結構考えたけど。
>>700 は都合が悪くなったのです
>>748
あなたはもしかして AranSK さん?
FP が理解出来なくてシェルスクリプトスレに来たの??
>>739=>>744=>>747=>>748 は必死なジサクジエンと言うことでよろしい?

昔話をしてもいいのなら、昔の方が「一つのコマンドの機能は必要最小限に」
というポリシーが強かったよ。複雑なことをするときは複数のコマンドの組み
あわせでやる(そして組み合わせにはパイプをつかう)、というのがUnixという
もののポリシーだと思われていたしね。

たとえば tar とかは、今時の GNU tar なら単独で tar.gz の展開もできるように
なっているけど、昔は gzip で展開してから tar に渡す、ということをしなくちゃ
いけなかった。

GNUツールは確かに便利だけれど、コマンドラインでのオプションが増えて
増えて、いわゆる昔の「Unix的」でなくなってきたような気がするなぁ。
>>750
自作自演ではないと思いますが。(つうかそんなこと推測するのはそもそも無意味)

でですね>>700のようなことを書いた文献とか一切見当たらないのですよ。
だから単なる脳内妄想なのか、他のことと間違えて覚えているのか…
752751:03/12/23 15:51
あ、>>739>>744は私です。
>>751
パイプに関する資料を調べれば?
プロセス間通信手段としてのパイプは古典的ながらも依然優れた手法だよ。

標準入力で読み込んで標準出力に吐出すタイプのプログラムは、そのパイプの
メリットを享受できるよね。
というわけで宿題の解答としては、

「複雑な処理をさせるプログラムを1つのプログラムとして記述することは、
デバッグするときや、後に一部の機能を使い回すときに作業効率が悪い。

例として信号のパワースペクトルを求める場合をあげる。
この場合、
* wavファイルをcsv形式に変換するプログラム(wav2csv)
* csvを読込んでそれを離散フーリエ変換するプログラム(fft)
* 読込んだ値の絶対値を求めるプログラム(abs)
にわけ、
$ cat test.wav | ./wav2csv | ./fft | ./abs > test.pow
と処理させる。
すると、wav2csv , fft , abs は他の場面でその機能が必要なときに使い回す
ことができる。

このように入力と出力を標準入力と標準出力で統一しておくことにより、
プログラムを機能にわけて部品化させることができ、
後にその部品を再利用することが可能になる。
パイプはこのようなプロセス間通信を実現する手段として最も容易であり、
かつ高速である。」

というようなことを書けば良いのではないかと。
って、宿題、というわけではないのか。。。。ごめん。
どうもまだわかってないようだな
>>754
ここでの議論はcatを使うことのメリットは何かってことだろ。
cat test.wav| ./wav2csv
>>688はcatのかわりにリダイレクトすればよいと言っている。
./wav2csv < test.wav
>>700はcatを使うと
>標準入力と標準出力でインターフェースを共通化
と言っているのだが、これが意味不明。
>>757はプログラムを書いたことがないんかな?

> ここでの議論はcatを使うことのメリットは何かってことだろ。

プログラムを書く側からすれば、プログラムの入力インターフェースとして
stdin だけ見ていればいいのは非常に楽だな。cat を使ってデータを stdin
にいれてくれるのならプログラムは書きやすい。

>>688はcatのかわりにリダイレクトすればよいと言っている。
> ./wav2csv < test.wav

それでどうやって多段パイプをする?
あぁ、誤解。すまん。 >>758 は読み違えていた。
結局>>700は都合が悪くなったのです。
死んだ馬にムチ打つのは少々気が引けるが…

「標準入力と標準出力でインターフェースを共通化しておくことのメリット」
でググッてみたらこのスレしかヒットしなかったよ。
762貝バンドのアンナ:04/01/09 18:07
シェルでpsqlコマンドを使いたいのですが、
下記の様にSQL文内の'の所はどの様に記述するのでしょうか?
sh-2.05b$ psql -c 'select to_char(update,'yyyy/mm/dd') from user;' database;
実行結果
ERROR: Attribute "yyyy" not found
となってしまいます。
>>762
一旦quote(')から抜けて、escapeした'を挿入し、再びquote(')に入ると
よいにゃん。例えば、「abc'def」をシェルに与えることを考えるなら、
echo 'abc'\''def'
とか試してみると原理がわかるにゃん。
escapeじゃなくdouble quoteで'をかこってもいいにゃん。
echo 'abc'"'"'def'
とか試してみると前のやつと同じ結果が見えるワン。
shell に展開されちゃうような記述がなければ、全体を double quote すればよさそうな気がする。
psql -c "select to_char(update,'yyyy/mm/dd') from user;" とか。
>762
ヒアドキュくわせればいーだろ。
766名無しさん@お腹いっぱい。:04/01/10 00:02
すいめせーん。
bashスクリプトで、引数のリストを配列として扱うにはどう書けば良いですか?

${@[0]}
↑これだとbad substitutionって言われちゃいます。。
元々配列じゃないものを無理矢理配列として扱う事はできません。
768名無しさん@お腹いっぱい。:04/01/10 14:23
どこに書くべきかわからないので, ここに書かかせてください.
tcsh の補間機能を使って screen -x の後にプロセスIDの一覧を出そうと
しています. 今こんな感じです.
complete 'n/-x/`screen -ls | awk ' "'" '{print $1}' "'" '`/'
で, awk でマッチする行を絞るのに,
complete screen 'n/-x/`screen -ls | awk ' "'" '$1 ~ /^[0-9]+\./ {print $1}' "'" ' `/'
としたのですが, 以下のエラーが出てうまくいきません.
Missing separator '/' after completion "`screen -ls | awk '".
これはどう修正すればいいのでしょうか ? screen -ls 以下を
別のシェルスクリプトにしておかないとだめですか ?
769名無しさん@お腹いっぱい。:04/01/11 00:58

770名無しさん@お腹いっぱい。:04/01/11 01:10
while文の中でrshを使うと1回実行されてループから抜けてしまいます。
正しくループさせる方法教えてください。

例)
『HOST_LIST』にはrshを許可したホスト名の一覧が含まれています

set -x
cat HOST_LIST|while read a;do
rsh $a date
done
>>768
tcsh を使わくなって暫くなるけど、クオートその他の代替表現は用意されていないのかな。
ネストできないのがつらい。解読するのが面倒なので自分の好きなように書くと
complete screen 'n@-x@`screen -ls | awk -F "\t" '\''/^\t/{print $2}'\''`@'
こんな感じだろうか。

>>770
read は一行しか読込まない。こんな風でいいのでは。
set -x
for h in `cat HOST_LIST`; do
rsh $h date
done
>>770
ごめんボケけてた。それで別に構わんよね。何故成功した時点で打ち止めに
なるのかはよくわかりません。
ああ、入力を取りあうことになるからか。
rsh $a date </dev/null
とでもすればいいのかな。
>>771
ありがとうございます. >>771 の書き方でも, >>768 の書き方でも
セパレータを @ にすることでうまくいくのを確認しました.
いつも vi を使ってるのに, complete でもセパレータを変えられるかもとは
全然思いつきもしませんでした.
あと >>771 のクォートの書き方も, 私のより綺麗に見えて勉強になります.
bashであるプロセスが終了してたらそのプロセスを起動するスクリプトを
cronに登録したいのですが、

もし"ps aux | grep プロセス名"が空なら"プロセス実行"

をどうやってスクリプトで書いていいかわかりません。
どうやって書けばいいでしょうか?
>>775
俺だったら、cronよりも、プロセスが終了したときに再起動する
wrapperを書くかな。↓こんなの

#!/bin/sh
while true
do
"常に立ち上げておきたいプロセス"
適当なエラー処理とかログとか。場合によってあきらめてexitとか。
done
777名無しさん@お腹いっぱい。:04/01/14 18:34
サブシェルで設定した変数の値を取得したいのですが
例)
 #! /bin/ksh
 export st=0;
 (st=1)
 echo $st
>775
ps aux|grep /usr/bin/hogehoge > /dev/null 2>&1
if [ $? != 0 ]
then
/usr/bin/hogehoge
fi

gnu grep だったら
ps aux|grep -q /usr/bin/hogehoge
779名無しさん@お腹いっぱい。:04/01/14 23:02
>777
サブシェルが短いなら、
st=`(st=1;echo $st)`
複雑なことしてるなら、一旦ファイルにおとして、
親シェルで読み込む。
でもこれってそもそも、盲点チックな方法だから
用途はかんがえたほうがいいんじゃ。
780775:04/01/15 03:53
>>778
ありがとうございました。
grepが見つからない時エラーを返すってところと、$?という変数があるところが
勉強になりました。
781名無しさん@お腹いっぱい。:04/01/25 05:03
テキストファイルから、全角2バイトの文字列を検出(grep?)させるには、
どうしたらよいでしょうか?


>781

漢字コードに依存してしまうけど、
ぼくだったら、
nkf -e <hoge.txt|grep "ほげ"
みたく、一旦eucにしてしまう。
>>782
マルチですよ。
784782:04/01/25 19:44
いートシして、マルチにひっかかってしまった!
ぎゃふん
とあるフォルダの中にあるファイルすべての名前を変更しようと思っている。

123あひゃ.txt
1234あひゃ.txt

ファイル名先頭の数字をすべて4桁で統一しようと思った。
そこで俺が書いたスクリプトは

mv $filename `echo $filename | sed 's/^[0-9][0-9][0-9]^[0-9]/0&/'`

これでめでたくフォルダの中身は

0123あひゃ.txt
1234あひゃ.txt

に統一された。
だがあらたな問題が生じた。
ファイル名の先頭に数字以外の文字が来ているのだ。

A123あひゃ.txt
B1234あひゃ.txt

これらを

A0123あひゃ.txt
B1234あひゃ.txt

に統一したいんだがどんなスクリプトを書けばいいんだろうか?
>785
むりくり一行にするんだったら、これ。
mv $filename `echo $filename | perl -ne 's/^(\D+)(\d+)(\D+)$/printf("%s%04d%s",$1,$2,$3)/e'`
>>785
一度4桁以上にしてから減らすのがミソ
mv $filename `echo $filename | sed 's/\([^0-9]*\)\([0-9]*\)\(.*\)$/\10000\2\3/;s/0*\([0-9]\{4\}\)/\1/'`
>>757

亀レスだが…最初の入力リダイレクトの前にフィルタを一つ追加する際の
手間が変わってくるということではないだろうか。

  cat ファイル名 | sort | uniq | wc -l
に対し、最初のフィルタに「grep HOGE」と思った時
  cat ファイル名 | grep HOGE | sort | uniq | wc -l
とすればよい。この場合、修正は
 (1) 「 | grep HOGE| 」挿入
のみ

だが
  sort < ファイル名 | uniq | wc -l
と直接書いていると
  grep HOGE < ファイル名 | sort | uniq | wc -l

 (1) 先頭に grep HOGE |」を挿入
 (2) sort の後の「< ファイル名」をカット
 (3) grep の後にペーストする
と3操作が必要となる。

これが面倒と言っているのでは?(それ以外、思いつかん)
長過ぎるスクリプトって読みづらいしメンテしたくないと
思うのですが、もともと構造のなさげなもの、どうやって
整理するのが正しいのでしょうか?
>>788
なるほど。それはありますね。
>>789
関数にするとか。
cat 云々よりも
>標準入力と標準出力でインターフェースを共通化
ケチが付いてたのはこっちの方。でも、もういいだろこの話は(w
792788:04/02/22 16:56
>>791

たしかに(藁
>>788
>>691にもあるけど、これだと修正の手間が同じだ。
<ファイル名 sort | uniq | wc -l
794名無しさん@お腹いっぱい。:04/03/24 00:50
ご教授ください。
別のスレに以下のような書き込みがあったんですが、

> "2001050202:20:26" (もしくは"20010502022026")
> みたく変換する関数をshellで定義すれば、
> この文字列は時系列的に大小比較可能

これは、「yyyymmddhhmm」の並びの文字列を、
指定された時間内か否かを、以下のような条件式で
判定できることを言っている?

 200403011200 < &NOW < 200404011200
[ 200403011200 \< $NOW -a $NOW \< 200404011200 ]
>>795
\<って使えるのか? -gtじゃないの?
それを言うのなら -lt じゃないのか。bash とかの組み込みコマンドでは、
< や > は文字列の比較に使うようだ。
「使い方が Perl と逆」で覚えてる。きっと俺だけじゃないハズだ。< or -lt
>>797
-ltでしたスマソ。zshではだめだったが、bashは使えた。
800794:04/03/25 00:27
皆さん、いろいろありがとうございました。
こんな感じ↓でもできました!

#必要な時間部分をファイルから抽出(":"区切りのファイル)
cut -c45-56 tmp1.txt > tmp2.txt
#第二フィールドの値をSTART_TIMEとEND_TIME内かどうか比較し、別ファイルに出力
awk -F: '{if( '$START_TIME' <= $2 && $2 <= '$END_TIME' ){ print $1 }}' tmp2.txt > tmp3.txt
801794:04/03/25 00:38
また別件で質問があります。
trコマンドで、ファイル内のNULL文字を、半角スペースに置換
しようとして、以下のようにコマンドを実行しました。

# tr '\000' '\020' < input.txt > output.txt

しかし、NULLが半角スペースに置換されるのではなく、
NULL文字部分が削除されて出力されました。
半角スペースに置換させたいのですが、この使い方は
間違っているのでしょうか。
ちなみに、Solaris8、コードはEUC、Bシェルを使用してます。
>801
Solaris8がどうなのかは分からないけど、tr が \0 を食ってしまうのは
ありえるような。
tr 以外で頑張ってみたら?
#!/bin/sh
tmpsrc=/tmp/junk$$.c
tmpbin=/tmp/junk$$
cat > $tmpsrc << END
#include <stdio.h>
int main(void) {
    int ch;
    while ((ch = getchar()) != EOF)
        putchar(ch ? ch : ' ');
    return 0;
}
END
cc -o $tmpbin $tmpsrc > /dev/null
$tmpbin
rm $tmpsrc $tmpbin > /dev/null
804名無しさん@お腹いっぱい。:04/03/28 21:14
すいません、初心者なんでくだらない質問しますが

シェルを使ってテキストファイルに書きこんだり、読みこんだりするにはどうすれば良いですか?
806804:04/03/28 21:43
>>805
ありがd

漠然とした質問でスマンカッタ

ちょと調べて見ます
うーん書き込みは分かったのだけれども
桁数を指定してシェル内変数に読み込むにはどうすれば良いのでしょうか…

808名無しさん@お腹いっぱい。:04/03/28 23:16
read使えばいいんでない?
809名無しさん@お腹いっぱい。:04/03/28 23:28
>>808
うーん、でもreadだと桁数の指定できないんじゃないですか?
>>807
適当なツール(sedとか)で加工すりゃいいだろ。
お前、その頭の固さじゃshellプログラミング向いてない。
811名無しさん@お腹いっぱい。:04/03/29 00:11
>>809
readで、無駄に変数たくさん作ってみる。

read a b c d e f g h i j k

必要な桁だけ使えばいい。
echo $c $f $k
>>810
組み込みコマンドだけでやりたいってことじゃないの?
組込みコマンドだけでシェルスクリプトが書けるはずがない。
すみません。対話式のコマンドをシェルスクリプトで実行することは
できるのでしょうか?

例えばあるコマンドにおいて、パラメータですべてを指定できるなら
シェルで実行できるのですが、パラメータには用意されていない
ものを、コマンド実行中に入力しなければいけない場合、
どのように記述すればいいか分かりませんでした。

できない場合はその旨を教えていただけると幸いです。
よろしくお願いします。
>>814
command <<EOF
parameter1
parameter2
EOF
で無理な場合は
expect
俺は使ったことないけど。
>>814

#!/bin/sh
read d
echo $d
817814:04/03/29 18:15
>>815
ありがとうございます。eofでは無理だったのですが、
expectではできそうです。ありがとうございました。
>>814
autoexpect使えば簡単。
勝手にシェルスクリプトができていく。
すみません、シェルスクリプトで、

set res = `cat test.txt`
echo "$res"

としても、test.txtの中身が取得できていません。
何が悪いのでしょうか?
820819:04/03/30 16:16
すみません、自己解決しました。
スペースをあけてはいけなかったんですね。
res=`cat test.txt`
でなりました。
test.txtが空とか?
822名無しさん@お腹いっぱい。:04/03/30 21:30
>>819
cat test.txt | ......処理..............

でいいだろうに。
824名無しさん@お腹いっぱい。:04/04/03 10:48
おせーて下さい

Linuxのbashなんですが

echo "aa bb cc"| read dd ee

でdd,eeがNULL何ですが、これってダメなんですか?

もう一つ
cat aa |while read aa
do
if [ $aa = "hoge" ]
then
bb=1
fi
echo $bb
done

echo $bb

ループ内のecho $bb は1が表示されますが
一番最後の echo $bb は値が表示されません

ループ内で定義した変数をループの外で使うことは出来ないのですか?
>>824
>echo "aa bb cc"| read dd ee
read はサブシェルで実行されるので、サブシェルが終了すると dd, ee は忘れられる。

>cat aa |while read aa
while はサブシェルで実行されるので(ry

ksh だとこれでもうまくいったような記憶が。
>>824,825
サブシェルで実行されるのはシェルスクリプト内でパイプを使って while に渡したときのみ。

-- fuga.sh --
#!/bin/bash
while read aa
do
if [ $aa = "hoge" ]
then
bb=1
fi
echo $bb
done

echo $bb

としておいて、

$ cat aa | ./fuga.sh

とすれば望み通りになる。
827名無しさん@お腹いっぱい。:04/04/03 11:27
>>825-826

ありがとさんです。
そうなんですよ、Solaris/kshで動いてたスクリプトを
Linux/bashにコピーしたら動かないんで悩んでました
(Linux初体験)

それまでkshでしかスクリプト書いたことが無かったもんで、
組み込み関数とかは同じようなものみたいだったんで
いけるかな、と思ったんですが、甘かった。

まぁ、そんなに複雑なスクリプトじゃないんで
ご助言を生かして、ぼちぼち改修していきます。
cat で渡さなくてもリダイレクトでいいのでは

#!/bin/bash
while read aa; do
if [ $aa = "hoge" ]; then
bb=1
fi
echo $bb
done < aa

echo $bb
>>824
826とほとんど同じだけど、パイプの後ろを単純に括弧で括ってしまうのが
簡単だと思います。元のスクリプトをほとんど変更しなくて済むし。

cat aa | ( while read aa
##echo $bbまで
)

>>825,826
パイプに参加しているものはすべてサブシェルになるので、その解説を読んで
「パイプの後ろだけサブシェルになるのか」と誤解する人がいそうな希ガスる。
実際、後輩でそう信じてたのがいたから。kshって結構違うんだよね。

>>801
trでNULLは使えなかったような。perlでも使った方が簡単で高速だと思います。
まあ、シェルのスレなんで、スレタイ的にこんなのどーですかw

od -v -t o1 | sed 's/^[0-9]* *//;s/ *$//' | egrep -v '^$' |\
sed 's/000/040/' | tr ' ' '\n' | sed 's/./& /g' |\
awk '{printf("%c",($1*64+$2*8+$3));}'
>>586
>echo *.jpg | sed -n 's/\(....\)\(..\)\(..\)_\(.\)\.jpg/mv & \1\/\1\2\/\1\2\3\/\1\2\3-\4.jpg/p' | sh
これってどういう仕組みで動いてるの?
sedの置換コマンドの中に入ってるmvがどういう処理をするのかわからない。
&はバックグラウンドで実行するということはなんとなく分かるけど。
元のファイル名はechoから受け取って、移動先のファイル名はsedから
受け取ってるのかな?
だれか教えてください
>>830
''でかこってるから、&はsedに渡されると思うけど。
>>830
うしろの | sh をはずして試してみるべし。
あとでフォローされてるように echo は ls の間違いなので注意。

>sedの置換コマンドの中に入ってるmvがどういう処理をするのかわからない。
どういう処理もしない。ただの文字列。

>&はバックグラウンドで実行するということはなんとなく分かるけど。
違う。man をよく読むべし。
833830:04/04/08 16:48
>>831
& の意味を man を読んで理解しました。

>>832
教えてもらったとおり echo を ls に変えて、
後ろの | sh を外してやってみたら...
おー!こういうことだったのか!
こんな方法考えもつかなかった。

>>831-832
ありがとうございました
834名無しさん@お腹いっぱい。:04/04/09 10:30
#!/bin/sh
i=1
while [ $i -le 100 ]; do
echo $i
i=`expr $i + 1`
done

これで1〜100まで表示されるんですが、
頭をそろえて
001
002
と表示したいのですが、どうやればいいのか教えていただけないでしょうか?
>echo $i

expr 00$i : '.*\(...\)'
>>834
for i in `seq -f %03g 1 100`
zshなら
for i in {001..100}
837名無しさん@お腹いっぱい。:04/04/09 10:53
>>835-836

ありがとうございます。
勉強になりました。
いまどきだとprintf(1)なんてのもあるよ。

djb スレよりこっちの方が適切かな?

qmail や daemontools の起動スクリプトの例を見ると、
csh -cf '/var/qmail/rc &'
のように、csh 経由でバックグラウンド起動させてます。
ttp://man.qmail.jp/jinstall/install3.html
ttp://www.emaillab.org/djb/tools/daemontools/svscan.html

これは SIGHUP を受けたときの sh と csh の挙動の違いを利用してると思うんですが、
そうじゃなくて nohup /var/qmail/rc & でいけない理由はあるんですか?

csh -cf 'nohup .... &' としてる例まで見つかるんですが、
わざわざ csh を使わなければならない理由があるんでしょうか。
ttp://www.unixuser.org/~euske/doc/daemontools/myfaq/faq-3.html#8
840名無しさん@お腹いっぱい。:04/04/23 08:43
新しい職場で、Solaris5.6上で動くcshスクリプトの山がorz

ttp://www.math.h.kyoto-u.ac.jp/~takasaki/edu/c/cshell.txt
以外に、「ここ読んでおけ!」的解説ページはありますか?
csh-whynotは、前任者に渡して小一時間問い詰めたい気分
>>840

csh は「たのしい UNIX」のせいで、利用者が増えてしまったからなぁ。
お世話になった人もいると思うが、結果的に見ると、悪所になって
しまったような気がする。
842名無しさん@お腹いっぱい。:04/04/26 16:02
Bシェル系で、printfってどのぐらい実装されてます?
portability低いなら、使わないんですけど…

今使っているのはzsh-3.0.5-nt-beta-0.75 というものです。
http://unxutils.sourceforge.net/ で拾ったものなのですけど…
843842:04/04/26 16:09
typeコマンドで見たら、printfは外部コマンドでした…失礼
まずはposixを参照のこと
845名無しさん@お腹いっぱい。:04/04/29 13:21
このスレいいっすね。「へー知らんかった」ということ多々あり。
ところで私もシェルスクリプトには非常にお世話になっていて、仕事でも
cygwin入れていろいろやっています。で、できたスクリプトを人にあげたり
いじってもらったりしたいという局面が出てきているのですが、今の職場では
シェルスクリプトは殆ど認知されておらずちょっと無理そうです。
で、代替を探しているんですが Java でシェルスクリプト感覚の文字列処理を
行える環境ってありませんか?あればそいつを ant 込みで配布してイイ感じ
に使えると思うんですが。。。みんなJavaはできるので。
具体的にはパターンや簡易なオプションでのファイル名取得やイテレート処理、
comm,sort,diffやらの文字列処理があればいいのかな。

ちなみに職場に受け入れられるかどうかを置いておくとベストソリューションは
Rubyかな、って思っています。日本語ファイル名もへっちゃらで
機能豊富、とっつきやすいから。#自分がRuby使えないんだけど。。。

偉大なシェルスクリプトマスターの皆様は私のような環境におかれたら
どうしますか??

python
>Java でシェルスクリプト感覚の文字列処理を
>行える環境ってありませんか?

Java っぽくて Java とシームレスに使えるスクリプト言語としては pnuts とか。
でも Java で文字列処理って明らかに無駄な労力のような気がする。
そんなこといったらサーブレットやJSP(まぁ文字処理が主な目的じゃないけども)、
1.4で導入された正規表現はどうなるんだ。
849761:04/04/30 03:18
>>847
ほしいのは UNIX の shell utility の「機能」といっても
いいかもしれません。sort, sed, awk, find, comm などの
洗練された入力、出力のフォーマット、機能などが Unix に拒否反応を
持っている人達に受け入れやすい環境で適用できたら、と思っているのです。
perl のモジュールにそんなのがあったような、なかったような。
個人的には perl や cygwin を入れさせたいんですがそれも一苦労だし
日本語関係でトラブルが予想されるのがちょっと…なのです。
850761:04/04/30 03:22
>>847
pnuts 見ました、こんなのがあるんですね。
http://www.ogis-ri.co.jp/otc/hiroba/technical/pnuts/

クラスを繋ぐ環境が手に入るのはいいのですが、文字列処理のために
繋ぎたいクラスがない、って感じですね。shell util のコードを
Java に移植する…うーん、難しいとは思わないがなんか無駄っぽい。

pnuts ですが bsh のほうが同様の環境としてはメジャーな
感じですね。何かいいとこあるんでしょうか。
WSH ってそういうやつじゃなかったっけ
852761:04/04/30 03:23
>>846
python は日本語ファイル名でこけませんか?
日本語の含まれるファイルの文字列処理は大丈夫ですか?
その調子じゃ布教は無理だろう
Perlでいいんじゃないの?
同感
javaやる人が日本語のファイル名なんか使うの?
857846:04/05/01 00:33
>>852
もち大丈夫です。
858761:04/05/01 13:52
>>863
まさに布教するどころかこちらが宗旨変えしたほうがよいのではないか、
という状況です。手順書作って「手でやれ」文化なんですよ。バッチ化は少し
時間がかかるから最初の2回ぐらいは手でやるほうがコスト安ですし。
ちょっとした処理はみなさんエクセルとか使ってその度手でやっているようです。

私自身は日本語ファイル名は使わない、とかいろいろ束縛を作ってその中で
作業してきたので、いざ何でもありの現場に入ってみるといろいろ試すのが
怖くなってます。CVS に日本語ファイルが突っこまれていたこともあって
自分が cygwin で作ったスクリプトがこけました。
859761:04/05/01 14:03
>>364
やっぱ perl になるんですかね。
日本語を含むファイルに正規表現使うと変なことになった記憶が
あるんですが回避策(jperl 以外)はありますか、ここらへんに
関して安心させてくれるドキュメントがありましたら教えてくださいませ。

Web開発をやっている職場なので Perl なら使ってもあまり
批難は受けずにすみそうです。これまで「シェルスクリプトで
できるからいっかー」と避けてきた Perl をやることに
しようと思います。心の中の声は「今さらPerl? Ruby とか Python とか
もっと洗練されているものを使えば〜」と言ってますが (^^;
もはや板違い
アンカーがグダグダ
>>853の意図を誤読?
洗練?
釣り?
黄金?

とりあえず上司に「もっと洗練されている社員を使えば〜」と言っておいて下さい。
>>860
>とりあえず上司に「もっと洗練されている社員を使えば〜」と言っておいて下さい。
Web開発なんて職場にそんな事考えられる上司すら居ないんじゃないかと思われ(ry
rubyもいいよ
863761:04/05/01 16:30
>>860
853の意図は存じておりますよ♪アンカーずれてごめんね。
混沌状態を飛ばしてひとあしとびに洗練された社員にはなるのは
難しいんですよ。うちも人的リソースは厳しいんで私が
頑張って洗練された社員になる予定です(w

おかげさまで考えがまとまりました、とりあえず UNIX shell 環境は
一時おさらばします。

>>849 >>850 >>852 >>858 >>859
このレスは全部 >>845 なんだろ?
なんで 761 なんだ? >>761 と同一人物なのか?
仮にそうだとしても分かりにくいぞ。

==
From: [859] 761 <>
Date: 04/05/01 14:03

>>364
やっぱ perl になるんですかね。
==
>>364 は awk について書いてくれてるんじゃないのか?


とりあえず少し落ち着いて整理してくれ。
コメントができない。



>>860 ももう少し優しくしてやれよ…
確かにイケテナイけど、せっかく聞いてくれてるんだからさ

865860:04/05/01 16:50
はいな。
866845 as 761:04/05/01 19:30
>>864
>>865
やばっ 761 を詐称してしまった…、それにアンカーも酷い…。
厳しいお言葉をいただくのもごもっともです。失礼すました。
>>866
どうしたらそこまで間違えれるのか。
868名無しさん@お腹いっぱい。:04/05/07 11:19
コマンドラインの結果を1行ずつ読んで細工する方法で
綺麗なのってないでしょうか?

例えば、あるディレクトリのファイルに .txt って拡張子をつける場合、

for i in `ls -1`
do
mv $i $i.txt
done

でいけそうですが、スペースもセパレートされてしまうので、
スペースを含むファイル名があると対応できません。
それで、こんなのを考えてみましたが、無駄が多すぎます。。
j=`ls -1 | wc -l | awk '{print $1}'`
c=0
while [ $c -lt $j ]
do
c=`expr $c + 1`
i=`ls -1 | head -${c} | tail -1`
/bin/mv "$i" "$i.txt"
done
確かこんなだったような。
一応自分で動作確認してくれ

set "*"
for i in $@
do
mv "$i" "$i.txt"
done
>>868
ディレクトリにファイルしかないというのなら、

ls | while read file ; do
mv "$file" "$file.txt"
done
871868:04/05/07 12:27
>>869-870
どちらもいけました。ありがとうございました。
list1.txtからlist2.txtに書かれているものを除外して表示するスクリプトを作っているのですが、綺麗な書き方を教えてください。
シェルはkshです。

自分が作ったのはコレです。

#!/bin/ksh

while read A
do
if grep -x "${A}" list2.txt > /dev/null 2>&1
then
true
else
echo "${A}"
fi
done < list1.txt
>>872
cat list1.txt list1.txt list2.txt | sort | uniq -c | grep 2

もし list1.txt や list2..txt の要素に 2 という文字が含まれるなら
最後の grep 2 をもう少し工夫しろ。
874872:04/05/13 22:11
>>873
なるほど、ありがとうございます。
「2」含まれる可能性あるのでこうゆう風にしますた。
cat list1.txt list1.txt list2.txt | sort | uniq -c | grep -E '^ *2' | cut -f2-

list1.txtを2個catしてるのはなにか意味があるのでしょうか?
↓でも(・∀・)イイ!!??
cat list1.txt list2.txt | sort | uniq -c | grep -E '^ *1' | cut -f2-
list1.txt を 2 個 cat すると、、、

list1.txt にも list2.txt にも含まれる場合は 3 個
list1.txt だけに含まれて list2.txt に含まれない場合は 2 個
list1.txt に含まれず list2.txt だけに含まれる場合は 1 個

となる。1 個しか cat しなかったら
list1.txt だけに含まれて list2.txt に含まれない場合と
list1.txt に含まれず list2.txt だけに含まれる場合が区別できない。
>>875
アタマイイ!
877872:04/05/13 22:26
>>875
なるほど、わかりますた。
grep -v -f list2.txt < list1.txt
でいいような気がするが違うんか?
俺もそれでいいと思うが、-f が使えない grep があるかもしれない。
メタ文字の扱い次第では fgrep の方がいいのだろうか
>>875
もまえ、頭良い。もれ、感激した。
list1.txt にダブリがないかチェックする必要があるな
>>879
メタ文字については-F(--fixed-strings)使えばいいだろう。

あと部分文字列の扱いをどうするかが明確じゃないような。
list2.txtにfooという行があったときにfoofooはどうなるか。
行全体でマッチなら-x(--line-regexp)も併用することに
なるだろう。
普通に>>872を読むと、行全体の完全マッチのように思うけど。
でもこの仕事はawkやperlで書いたほうが同じぐらいのコードで
しかも速くできるような気がする。list2.txtがそれほど大きく
ないなら、list2.txtの内容をhash setに突っ込むのが一番はやいんじゃないの
ワンパスで済むし。
awk使っていいなら

awk 'BEGIN{ while(getline l < "list2.txt"){a[l]=1}} {if(!a[$0]){print}}' list1.txt

てなとこかなー。300行ぐらいのてきとうなファイルで

grep -v -x -F -f list2.txt list1.txt

と比べてみたけれども、grepは0.4秒ぐらいでawkは0.01秒(あまり正確じゃない)
だった。
>>884
予想通りawkのが速いけど、その程度ではあまり意味のない差とも言えるな(w
まーまじめにリレーショナルの差集合じみた演算を実装したいんなら
オンメモリの連想配列頼りというのも不安だから、実はまじめに
プログラムを書く余地があるということか。
「まさにそのもの」というコマンドが無いのは結構意外かも。
>>885
どっちも1秒以内だしこれならタイピング時間の差でgrepが速い
ことになりそうだ(笑)

grepの方はlist1.txtとlist2.txtの行数の積に比例するのですぐに
とんでもないことになるかもな。

連想配列がメモリにのらないほどになったら、perlでdbmにtieした
ハッシュ使えばいいだろう。ほとんど手間は変わらない。
join
>>886
あ、確かにPerlならそれが一番賢いわな。
ってどんどん原始的でなくなってるが……(w
>>887
そんなコマンドがあるなんて、しらなかったYO.
しかもPOSIXで定義されてる……。
commってのもあるね
あれ?
いま、joinのman読んだけど、これってリレーショナルで言う
INNER JOINしか実現できないんでないの?
これで差集合、とれる?
892872:04/05/17 19:06
3パターンで試してみますた。

list1.txt 13062行
list2.txt 11792行

$time grep -v -x -F -f list2.txt list1.txt
real 4m0.58s
user 3m48.96s
sys 0m0.27s

$time awk 'BEGIN{ while(getline l < "list2.txt"){a[l]=1}} {if(!a[$0]){print}}' list1.txt
real 0m0.78s
user 0m0.72s
sys 0m0.03s

$time cat list1.txt list1.txt list2.txt | sort | uniq -c | grep -E '^ *2' | awk '{print $2}'
real 0m2.04s
user 0m1.94s
sys 0m0.05s

2番目のawkが断然速いのですが、変数にガンガン入れてメモリが心配になったので3番目のやつを使うことにしますた。
893>>872:04/05/17 21:12
/. より参考になる(+1)
メモリ使用量という観点からは、3番目のsortの使用量が、2番目のawkの使用量より
3倍近く多くなると思うが実際のところはどうなんだろう。awkの配列が冗長だと
3番目より多くなるのかな。
>>892
わざわざ質問して→複数の回答をもとに性能比較して
などという検討フェーズ持つ時間があるんなら、もっと凝ればいいのに(w
それ、どれも使い捨てのワンライナーじゃん。

メモリが不安ならDBM使えばヨシ、という案も出てるでしょ。まあperl他が前提に
なっちゃうけどな。
896872:04/05/17 21:41
>>894
変数いっぱい使ってるから重くなるんじゃないか?っていう素人な考えなのですが、実際のとこどうなんでしょうかね。
本番機で流すのでなるべく負荷が少ないほうがいいんですが・・・。
>>896
ちょいかえて、
cat list1.txt list1.txt list2.txt | sort | uniq -c | awk '$1==2 {print $2}'
が一番かな?メンテ効率を考えると、3秒で理解できるし。
awk '$1>2 {print $2}'
にも変更きくのが強み。
comm -23 list1.txt list2.txt
899872:04/05/21 22:49
>>898
まさにコレっていうコマンドあったんですね。
ありがとうごぜいます。
(´-`).。oO(不憫な >>890 …)
901 :04/06/23 15:31
.
902名無しさん@お腹いっぱい。:04/06/24 02:01
コマンド | while read LINE
do
    処理
    echo '次逝って(・∀・)イイ??'
    read ANSWER
    処理
done

ってことをしたらコマンドの結果が'read ANSWER'にも食われちゃいました。
正しく動作させるにはどーしたら良いでしょーか?
read ANSWER </dev/tty
#!/bin/sh
/bin/sh $0
>>903
やってみたらbashではうまくいったけどzshではうまくいかなかった。
なぜだろう?
906902:04/06/24 12:15
ありがとうございます。kshでうまくいきました。
ちなみに私の環境だとzshでもいけました。
$ zsh --version
zsh 4.0.6 (i386-redhat-linux-gnu)
907/:04/07/16 18:39
/
emacsをemacsclientとして起動してるんですが、、emacsがひとつも起動してない場合はemacsclientではなくemacsを起動する、みたいなscriptはどのように書けばよろしいのでしょうか?

909名無しさん@お腹いっぱい。:04/07/17 00:28
シェルの中のコマンドの戻りがほしいんだすが。
例)
aaaを実行するとパスワードを聞かれます。
確認の為、2回パスワードを聞かれます。
それをシェル実行時のパラメータで渡して、実行しいのですが
うまくいきません。
ヘルプミー

#!/bin/sh

/usr/local/bin/aaa

$1

$1

echo "Finish"

そうすれば2回のパスワードを入力した状態にできるのでしょうか?
>>909
expect
FAQ すぎる。
>>908
emacsclient || emacs
912909:04/07/17 01:23
>>910
レスthxです。

動くのですが、1回目は必ず失敗します。
Ctrl+Cで抜けて、もう一回叩くと成功します。

一回目失敗するのは
Enter password: test

ここで止まってしまいます。
2回目は必ず成功します、、、、、
何か間違った記述をしていますでしょうか?


#!/usr/bin/expect

set passwd [lindex $argv 0]

set timeout 10

spawn /usr/local/bin/aaa

expect "Enter password:"

send "$passwd\n"

expect "Verify password:"

send "$passwd\n"

interact
913909:04/07/17 04:17
>>912
自己解決しました

send "$passwd\n"

ダブルクォーテーションがいりませんでした。

send $passwd\n

とやったらうまくいきました
ログイン中に実行した全てのコマンドの出力をログファイルに逐一記録していくというのはどうすれば実現出来ますか?
全コマンドにパイプでteeを通せばいいと思うんですが・・・。
>>914
ttyrec?
916914:04/07/17 16:23
>>915
ttyrecとは面白そうなものがあるんですね。
文字列が取れれば良いだけなので、これの元版である script コマンドを利用することにします。
ありがとうございました。
917914:04/07/17 16:27
ちなみに、用途はリモートのサーバ管理でrpm等のコマンドログを記録し、後でアンインストールや
分析のために使うといったものです。完全な依存性解決が出来ないものや、アンインストール時に
残る設定ファイルのバックアップを削除する、等に有用そうです。(常識なのかもしれませんが)
shell の history って話ではないの?
(-_-)ウツダ
そんな話ではなかったですね
920名無しさん@お腹いっぱい。:04/07/27 19:12
$cat set.txt
export A="hogehoge"

$cat hoge.sh
#/bin/sh
. ./set.txt
echo "$A"

ってな感じで変数をセットして処理してるんですが、外部ファイルからセットするやり方はコレで正しいですか?
それとも専用のコマンドとかありますか?
あと、set.txtのような設定ファイルの拡張子は慣習的にコレ!ってゆうのはありますか?iniかな?
>>920
私はこんな感じでやってます.
$ cat set.txt
#!/bin/sh
COMMAND='A="hogehoge" '$@
eval $COMMAND
exit $?

$ cat hoge.sh
#!/bin/sh
echo "$A"

$ ./set.txt ./hoge.sh
hogehoge

./configureする前にCFLAGSとかCXXFLAGSとかに最適化フラグを設定したいときなどは,
これでやってます.
ですんで,上記set.txtにあたるファイルの名はexecute_with_flag_optimaizeにしてて,
$ execute_with_flag_optimaize ./configure --prefix hoge
なんてやってます.
>>921
なかなかいいんだけど、evalのところで、""の情報が消えないか?
./set.txt touch "hoge fuga"
とかやったとき
923921:04/07/28 09:32
>>922
そうですね.解決策ないですか?
924922:04/07/28 10:00
こんなかんじで一応できるようだ。

$ cat quote.sh
#!/bin/sh
for i
do
echo -n \"$i\"" "
done

$ cat set.txt
#!/bin/sh
COMMAND='A="hogehoge" '`quote.sh "$@"`
eval $COMMAND
exit $?
925922:04/07/28 10:13
というか
#!/bin/sh
A="hogehoge" "$@"
これでいいじゃん。
926921:04/07/28 10:29
>>925
!なるほど.
しかし私はなんで921みたいにやったんだろう?
927名無しさん@お腹いっぱい。:04/07/31 02:11
変数に文字列を入れたいのですが,その文字列はいろいろなコマンドや awk をパイプで
通ってきたものなんです.
一旦ファイルに入れる以外に,どう書いたら良いのでしょうか.
クォートやエスケープだらけで混乱してしまいます.

emacs のモードがやってくれれば,いくらかマシなんですが...

hoge=`while test -ge 1; do ... ; shift; done | awk '... {...} ...'`
>>927
一行野郎でやりたいわけ?

#ところで'-ge'の左辺はどこに消えた?
つか、具体的にどんな処理をしたいの?
それを書かなきゃ何も判らん罠。
ちゃんと相談する気があるなら、今宵は暇だから付き合ってやってもいいぞ。
>>927
その「いろいろなコマンド」を ` ` の中に書けばいいだけでは。
「いろいろなコマンド」の中で ` ` を使ってるようなら、
最近のシェルの場合は ` ` の変わりに $( ) を使うとネストしやすい。
shiftを使ってるって事は一行野郎ではなさそう。
awk絡みのクオートがややこしいと感じるならawkスクリプトを別ファイルに書いたら?

hoge=`while test $# -ge 1; do ... ; shift; done| ./fuga.awk`
932927:04/08/01 19:14
レスが遅れました.ごめんなさい.
夜遅くでしたので,既に考え方に無理があったのかも知れません.

>>928
ファイルに書いて使うシェルスクリプトです.
「こんな感じ」という意味で書いたのに間違えていましたね.左辺は $# で,
ファイル名です.awk が gnuplot に与えるコマンドの一部を作ります.

それを後でちょっと変えて,最後に gnuplot の set と一緒に gnuplot <<EOF の中に
書こうと思ったのです.

>>929
あぁ...書いた後すぐダウンしました.夜は粘れなくて...

引数に与えたファイルの数だけ
"filename" using 1:2 ,\
"" using 1:3 ,\
を増やそうと思ったのですが,最後のファイルについての 2 行目は
,\ を出力してはいけないんです.
なので,ここは awk でやり,文字列を変数に受け取ろうと思いました.

gnuplot には,グラフの設定にあたる部分と,このプロットをする部分とを
gnuplot <<EOF の中で結合して渡そうとしました.

そこで,どうすればプロットする部分を変数に入れておけるのかな,と思ったのです.
933927:04/08/01 19:21
>>930
こんなのがあるんですか.
bash なのに bourne shell っぽくストイック書いていましたが,
この際 bash をフルに使ってみようと思います.

>>931
あまりファイルを増やしたくないのと,中途半端な機能しかないのを分離すると
ディレクトリが汚れてしまうので...
934名無しさん@お腹いっぱい。:04/08/05 13:59
対話的に現在入力中の一つ前の引数に置換されるのってありましたよね?
なんでしたっけ?

% cp file !$.bak
みたいにやって、file.bak にしたいのですよ。
935934:04/08/05 14:14
使ってるのはzshです。
% cp file !#$.bak
みたいなのでいいのかな。

でも、対話的に使っているのなら zsh では copy-prev-word を使った方が楽なような。
大抵の端末なら Esc-C-/ で OK
937!934:04/08/06 23:46
>>936
おー知らなかった。結構使い道ありそうだね。
938名無しさん@お腹いっぱい。:04/08/07 11:31
bshで環境変数に環境変数名がある時、その環境変数名の値を取り出すにはどうしたらようですか?

AAA="aaa"
BBB="AAA"

のときにBBBからaaaを取得したいんです
>>938
eval echo \$$BBB とか。
つーか、環境変数じゃなくてただの変数では。
940名無しさん@お腹いっぱい。:04/08/07 20:58
>>939
ありがとうございます

で、またまた質問なんですが

====test.sh===========
#!/bin/sh
AAA="aaa"
BBB="AAA"
CCC=`eval echo \$$BBB`
echo "CCC [$CCC]"
===============

$ test.sh
としたばあい

CCC [2256BBB]

となってしまいます
予想では

CCC [aaa]

となつと思ったのにさっぱりわかりません
#!/bin/sh
AAA="aaa"
BBB="AAA"
eval CCC=\$$BBB
echo "CCC [$CCC]"
漏れは aaa command not found とかになるかな,とか思ったのに,
なぜか実行できた.どうして? エロい人!
>>940
` ` の中の \$ が $ に置換され
その後 $$ が PID に置換されてるんでは。
だから
CCC=`eval echo \\\$\$BBB`
とすればいい。
945名無しさん@お腹いっぱい。:04/08/08 15:29
csh使ってるんですが、あるコマンドが";"で区切られた引数を要求するんで

#!/bin/csh
set cmd="/usr/sbin/foo --options='100;200;1;3' -exec"
$cmd

とscriptに書いたのですが、";" が邪魔をして上手く実行できません。
どのように書けば ";" に邪魔されずに $cmd が実行できるんでしょうか?
エスケープしてみろ
動くかどうかは知らんが。
947名無しさん@お腹いっぱい。:04/08/08 21:30
grep "hoge" $file | while read tmp
do
done
echo $tmp

とすると、$tmpの中身が表示されません。
echo $tmp
をdoの中に入れると表示されるんですが、
doの外でも動作させるにはどうすればいいですか?
>>947
そのスクリプトがやりたいことは,
grep "hoge" $file | tail -1
ですよね?

while ...; do ...; done
内の変数を外に出したいとすれば,,,,,,$(...) に入れるとか?
>>947
子プロセスが上がるから、だっけ?
>>947
それ、別プロセス以前に、最後の read が $tmp を空にしてる気がする。

とりあえず、
seq 10 | ( while read tmp; do tmp1=$tmp; done; echo $tmp1 )
みたいにしたら、 tail -1 みたいな動作はしたよ。
951947:04/08/09 08:51
>>948-950
あ、そうか。
whileでEOFを読んじゃってるのか。
そりゃ空になってますね。
ありがとうございました。
他の方法でやってみます。
すみません質問なんですが、
Kshで、片方若しくは両方の変数に2ギガを超える数値を設定して
[[ $inumA -gt $inumB ]]
のような条件式を使うと期待した結果が出ないのですが

対応策のようなものをご存知の方居たらご教授いただきたく。
ちなみにOSはHP-UXです
perlかawk使えと怒られそうですが。

cshでファイルに書かれている内容を1行ずつ処理をしたいのですが、これって
やっぱり無理なんでしょうか?
>>952
ハードのモデルは?
HP-UX のバージョンは?
>>952
確か、桁が多い数値の比較はbcコマンドでやればいいんじゃなかったかな。
956952:04/08/10 22:36
>>954
ハードは多分HPです。
OSは11.00でした。

>>955
シェルでbcコマンドって使ったことがないのですが
自分の例で行くと
[[ `echo $inumA | bc -l ` -gt `echo $inumB | bc -l ` ]]
のような形になるのでしょうか。(-gtは>になる??)
ともあれ早速試してみます。ありがとうございます(ぺこり)
957955:04/08/11 00:06
>>956
確かこう。
A="1234567890999"
B="2234567890999"
if [ "$(echo "${A} < ${B}" | bc)" -eq 1 ]
then
echo ok
fi
958955:04/08/11 19:49
>>956
スマソ。957のはcygwinでは出来たけどHP-UXじゃ出来ないかも。
こんなのはどお?

export A="12345678999999999"
export B="22345678999999999"
if awk 'END{if(ENVIRON["A"]+0 > ENVIRON["B"]+0) exit 1}' /dev/null
then
echo ok
fi
とある環境変数が、
- そもそも定義されていない
- 定義されているけれども、値が「""」(空白文字列)である
を sh で判定する方法を教えてください。

現在は set を使って以下のような醜い方法で判定しています。

#!/bin/sh

isDefined(){
set | grep "^${1}=" > /dev/null && return 0
return 1
}

x=""

isDefined x && echo "x is defined" || echo "x is not defined"
isDefined y && echo "y is defined" || echo "y is not defined"
>>959
printenv
% cat hoge.sh
#!/bin/sh
x=""
echo ${x+"x is defined"}${x-"x is not defined"}
echo ${y+"y is defined"}${y-"y is not defined"}

% sh hoge.sh
x is defined
y is not defined
>>960
以下のように試してみましたが、ヒントから手がかりがつかめません。
もうちょっとヒントください。(-人-)

#!/bin/sh
x=""
printenv $x
echo $?
printenv $y
echo $?

>>961
面白くて参考になります。ありがとうございます。
「定義されているかどうかをチェックする」関数にしたいという希望があったため、
以下のようにしました、、、んが、頭が悪く、スマートな方法が思いつきませぬ。
関数として定義する場合で、もっと頭の良い方法ってあるでしょうか?

#!/bin/sh
isDefined(){
if [ `eval "echo \\${$1+\\"0\\"}\\${$1-\\"1\\"}"` != "1" ]; then
return 0
else
return 1
fi
}

x=""
isDefined x && echo "x is defined" || echo "x is not defined"
isDefined y && echo "y is defined" || echo "y is not defined"
最初に環境変数って言ったから printenv が出てきたんだと思う。
本当に環境変数なら俺も printenv に一票入れるが、
どうもやりたいことは違いそうだな。
>>962
仕様をよく読んでないけど test -z じゃだめなん?
965952:04/08/16 23:55
>>955

返事遅れてすみません。
>>957のほうは今日試してみて稼動確認取れました。
>>958はまだ試してないんですが、今度チャレンジしてみたいと思います。
本当にありがとうございました
966955:04/08/17 00:46
>>965
957のほうで出来ましたか。オレが試したHP-UXだと出来なかった。
最近知ったんだけど、こっちのほうがいいかも。解かり易い。
if expr ${A} '>' ${B} > /dev/null
then
echo ok
fi

bc,awk,expr、桁の制限でいったらどれが一番イケるんだろ?
>>959 は、
環境変数→変数
空白文字列→空文字列
の間違いか。

>>962
961ではないが、こんな感じでいいのかな。

#!/bin/sh

isDefined () {
if eval [ x'${'"$1"'+0}' = x"0" ]; then
return 0
else
return 1
fi
}

x=""
isDefined x && echo "x is defined" || echo "x is not defined"
isDefined y && echo "y is defined" || echo "y is not defined"

zsh だと ${+name} みたいなものもサポートされているようだが。
isDefined(){
eval return \${${1}+0}\${${1}-1}
}
>>968
それだと値が入っているときにおかしくならないか?というわけで、、

isDefined(){
eval \${$1+true} false
}