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

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

■ このスレッドは過去ログ倉庫に格納されています
0001ミスターシェル2006/09/07(木) 13:00:11
シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>1-6くらい)をご覧ください。


□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashなので特に注意。
・csh/tcshのシェルスクリプトは推奨されません。
(理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
 manや参考リンクを見ましょう。
 aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)

□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
0127名無しさん@お腹いっぱい。2006/10/07(土) 20:32:36
やっぱ bash使えば直るよねぇ
0128名無しさん@お腹いっぱい。2006/10/07(土) 22:39:17
echoがエスケープシーケンス解釈しないのはBSD由来なわけだが。
んで、echoがエスケープシーケンスをデフォルトで解釈するビルドもできちゃう
どっちつかずなbashがGJなのかよw
0129名無しさん@お腹いっぱい。2006/10/08(日) 00:09:40
デフォルトは有効でもいいが、オプションで無効にできたりするといいがな。
0130名無しさん@お腹いっぱい。2006/10/08(日) 01:13:22
大多数のshができないものは基本無効、オプションで有効だろ?
0131名無しさん@お腹いっぱい。2006/10/08(日) 06:43:25
ちゃうだろ。
Solarisなどのecho(/bin/echoも含む)が、エスケープシーケンスを無効にする方法がないことをいってるんジャマイカン?
013295-1012006/10/10(火) 14:04:36
m(_ _)m アリガトォ〜 ゴザイマス★

/usr/bin/sed /usr/ucb/sed /usr/xpg4/bin/sed でも動作しました。
0133名無しさん@お腹いっぱい。2006/10/16(月) 01:05:51
sambaで共有している関係で「スペース」の入ったdirがある状況で、
特定拡張子のファイルを一括処理しょうと思い、

for file in `find . -name "*.hoge"`
do

のようにやると、スペースごとに変数fileに入ってしまうのだが
簡単な回避方法ありますか?


0134名無しさん@お腹いっぱい。2006/10/16(月) 01:25:32
find . -name "*.hoge" | while read line;do echo "@ $line @";done
0135名無しさん@お腹いっぱい。2006/10/16(月) 01:40:44
>> 134

ありがと。勉強になりました。
while 使えば行処理できたのか〜。

0136名無しさん@お腹いっぱい。2006/10/16(月) 03:24:33
与える先がxargsなら
find ... -print0 | xargs -0
もあり。
0137名無しさん@お腹いっぱい。2006/10/17(火) 17:36:58
変数 $1111 には

aaa
bbb
ccc
ddd
eee
fff

といった文字列(6行)が入っている。


変数$2222には

bbb
ccc

といった文字列(2行)が入っている。
$2222の中身を、「1行ずつ」grepキーワードとして、


cat $1111 | grep bbb
cat $1111 | grep ccc

と個別にcatを実行したい。
どうしればいいだろう。
0138名無しさん@お腹いっぱい。2006/10/17(火) 17:41:22
宿題は自分で。
0139名無しさん@お腹いっぱい。2006/10/17(火) 17:47:04
>>137
$2222 って、2,222個目の引数のことだぞ。普通のシェル変数じゃない。
で、勝手に $hoge1 $hoge2 と置き換えさせてもらうが、答えは echoを使うこと。

echo "$hoge1" | grep bbb
echo "$hoge2" | grep ccc

ダブルクォート " " で囲むのが重要。
0140名無しさん@お腹いっぱい。2006/10/17(火) 17:47:43
変数$2222の値を見ながら手でコマンドを入力する。
0141名無しさん@お腹いっぱい。2006/10/17(火) 17:49:36
すでに >>139 が正解を書いたあとにボケたつもりの >>140 が不憫。
0142名無しさん@お腹いっぱい。2006/10/17(火) 18:21:59
いや139は正解じゃないだろ... $2222でループまわすことが求められていると思うのだが。
0143名無しさん@お腹いっぱい。2006/10/17(火) 18:30:25
いや、問題自体が間違っている >>137 が悪いな。
後付けで問題訂正されるより、 >>137 がもう一度正確な問題を書くまで待機した方が良さそう。
0144名無しさん@お腹いっぱい。2006/10/17(火) 18:33:44
もしかしてこういうことか?


for keyword in $hoge2
do
echo "$hoge1" | grep "$keyword"
done

$hoge2のところは " " なし(←これ重要)
$hoge1のところは " " あり(←これ重要)
0145名無しさん@お腹いっぱい。2006/10/17(火) 18:38:15
echo じゃなくて cat でしょ?
0146名無しさん@お腹いっぱい。2006/10/17(火) 18:39:32
>>145
だから、catだと勘違いしてる >>137 の問題が間違いだろ。
0147名無しさん@お腹いっぱい。2006/10/17(火) 18:41:20
>>146
勘違いかどうかわかんないじゃん。
決めつけはよくないよ。
0148名無しさん@お腹いっぱい。2006/10/17(火) 18:43:56
>>145
オマエアフォだな。もし catだと、
aaa
bbb
ccc
ddd
eee
fff

という改行付き6行もある変態的なファイル名のファイルを読み込むことになるんだよ。
echoの間違いだとエスパーしてあげたのは親切と言えよう。
0149名無しさん@お腹いっぱい。2006/10/17(火) 18:45:20
だからぁ、>>137 がもう一度正確な問題を書くまで待機しろ、と言っただろ。
0150名無しさん@お腹いっぱい。2006/10/17(火) 18:48:00
本当に catなら、「catが無駄です」の例になるな。
↓こういうことか?

for file in $hoge1
do
for key in $hoge2
do
grep "$key" < "$file"
done
done
0151名無しさん@お腹いっぱい。2006/10/17(火) 18:50:42
>>148
変態的なファイル名の可能性もあるし、
複数のファイル名が変数に格納されてるのかもしれない。
勝手な解釈しちゃいかんよ。
0152名無しさん@お腹いっぱい。2006/10/17(火) 18:54:55
いや、実際に bbb とか ccc とか、grepで一致する例が含まれてるし、
変数 $1111 改め $hoge1 の内容はファイル名じゃなく、文字列そのものだろ。

>>144 のエスパー(echo)が正しいに1票。

>>150 だと、「変数 $1111には1行ずつファイル名が入ってます」とかいう表現になるはず。
0153名無しさん@お腹いっぱい。2006/10/17(火) 18:58:04
>>152
その可能性もあるけど、あくまで可能性。
そこは本人に言わせなきゃだめだよ。
0154名無しさん@お腹いっぱい。2006/10/17(火) 19:02:18
ほんにんはにげだした・・・
0ポイントのけいけんちかくとく
01551372006/10/17(火) 22:47:25
>>139
あ、そうだった。1111番目のひき数って意味ではなく、ご認識の通り。
catはファイル名対象が前提なんですね。
スクリプト内での処理ですので、echoのことです。訂正します。

>>144氏ので行けそうな気がする。ありがとうございます>各位

今回は"ファイル名"というものは存在しません。
01561372006/10/17(火) 22:59:57
Cygwin動かないので明日会社で試す。
というか、変な質問してしまったことに今気がついた。
迷惑かけた。

今日8時間ぐらいずっとそれで悩んでたんだ。
googleで調べるとreadって命令を見つけたのでずっとそれと格闘してた。
0157名無しさん@お腹いっぱい。2006/10/18(水) 10:08:51
>$hoge2のところは " " なし(←これ重要)
>$hoge1のところは " " あり(←これ重要)

これなんで?
あっても無くても同じじゃないの?
0158名無しさん@お腹いっぱい。2006/10/18(水) 10:13:48
>>157
word splittingが行われるので違ってくるんだな。

0159名無しさん@お腹いっぱい。2006/10/18(水) 10:14:10
同じじゃないよ。
0160名無しさん@お腹いっぱい。2006/10/18(水) 10:14:37
for keyword in $hoge2
do
echo "$hoge1" | grep "$keyword"
echo TEST
done

別人だけど、これを実行しても

aaa
bbb
ccc
ddd
eee
fff
TEST

と表示されてしまうぞ。

bbb
TEST
ccc
TEST

とならなってくれないとおかしいのでは。
01611572006/10/18(水) 10:17:06
つまり、

echo $hoge1

としたのでは、
下手すると

$hoge

という文字列そのものが表示されてしまう恐れがあるってことかな。
0162名無しさん@お腹いっぱい。2006/10/18(水) 10:36:34
単語の分割

シェルはパラメータ展開・コマンド置換・算術式展開 (ダブルクォートの内部ではこれらの展開は行われません) の結果をスキャンし、
単語分割 を行います。シェルは IFS のそれぞれの文字を区切り文字として扱い、他の展開の結果をこれらの文字によって単語に
分割します。 IFS が設定されていないか、その値が正確にデフォルト値の <スペース><タブ><改行> ならば、 IFS 文字の任意の列
で単語が区切られます。 IFS がデフォルト以外の値を持っていれば、空白文字 (スペース および タブ) の列は単語の先頭と末尾
では無視されます。これは空白文字が IFS の値 ( IFS 空白文字) に含まれる限り成り立ちます。 IFS に含まれ、 IFS 空白文字で
はない文字は全て、隣接する任意の IFS 空白文字と一緒になってフィールドの区切りとなります。 IFS 空白文字の列も区切り文字
として扱われます。 IFS の値が空文字列であれば、単語分割は全く行われません。


明示的に指定した空の引き数("" または '')は削除されずに残ります。クォートされていない暗黙的な空の引き数が、値を持たない
パラメータを展開した結果として得られますが、これらは削除されます。値を持たないパラメータがダブルクォート内部で展開される
と、これは空である引き数となり、消されずに残ります。

展開が行われなければ単語分割も行われない点に注意してください。
0163名無しさん@お腹いっぱい。2006/10/18(水) 10:42:40
echo ${hoge1}

これでもいいんだよね
0164名無しさん@お腹いっぱい。2006/10/18(水) 11:20:16
>>163
だめ。

echo ${hoge1} と echo $hoge1 は全く同じ。

echo "$hoge1" と同じなのは、echo "${hoge1}"
0165名無しさん@お腹いっぱい。2006/10/18(水) 11:24:00
>>160
zsh 使ってるんじゃない?

zsh だと、$hoge2 と書いても "$hoge2" と同じに解釈される糞仕様なので、、、
shかbashでやってみろ。
0166名無しさん@お腹いっぱい。2006/10/18(水) 11:41:14
>今日8時間ぐらいずっとそれで悩んでたんだ。
0167名無しさん@お腹いっぱい。2006/10/18(水) 11:44:17
>>166
どうしたの?
0168名無しさん@お腹いっぱい。2006/10/18(水) 13:51:26
質問です。

ファイルに ID,ファイル名,1,sed7s/(正規表現)正規表現/正規表現/',と並べてます

for LINE in ${LINE} ; do
IFS=','
FILE="$1"
SW="$2"
CMD="$3"

case $SW in
"0" )
コピーするだけ。;;
  "1" )
cat $FILE | $CMD" > hogehoge ;;
esac
done <ファイル
echo "$hoge1" | grep "$keyword"


done <FILE

どやってみたのですがうまくいきません。
設定ファイル上にかかれた正規表現や変数を含むコマンドを実行するには
どうしたらよいのでしょうか?
0169名無しさん@お腹いっぱい。2006/10/18(水) 13:52:49
下記二行は間違いです
>echo "$hoge1" | grep "$keyword"
>done <FILE
0170名無しさん@お腹いっぱい。2006/10/18(水) 14:30:50
syslog02# cat list.txt
EAST,01,blue,192.168.1.1,3:1
EAST,03,blue,192.168.1.1,3:2
EAST,05,green,192.168.1.2,3:3
EAST,03,green,192.168.1.2,3:8
EAST,05,red,192.168.1.3,3:12

syslog02# cat 2ch_sh
#!/usr/local/bin/bash
IFS=$'';SORT=(`cat $1 | sort -t, -k3`)
IFS=$'';UNIQ=(`cat $1 | sort -t, -k3 | awk -F , '{print $3 }' | uniq`)
for keyword in "$UNIQ"
do
echo "$SORT" | grep "$keyword"
echo test  (本当はここでファイルを作成したい)
done
------------
0171名無しさん@お腹いっぱい。2006/10/18(水) 14:33:46
【理想】
syslog02# ./2ch_sh list.txt
EAST,01,blue,192.168.1.1,3:1
EAST,03,blue,192.168.1.1,3:2
test
EAST,05,green,192.168.1.2,3:3
EAST,03,green,192.168.1.2,3:8
test
EAST,05,red,192.168.1.3,3:12
test
【現実】
syslog02# ./2ch_sh list.txt
EAST,01,blue,192.168.1.1,3:1
EAST,03,blue,192.168.1.1,3:2
EAST,05,green,192.168.1.2,3:3
EAST,03,green,192.168.1.2,3:8
EAST,05,red,192.168.1.3,3:12
test
0172名無しさん@お腹いっぱい。2006/10/18(水) 19:00:48
>>168
全然駄目。shの文法を読み直す。set -xで動作を追跡することを憶える。
その上で判らない場合に出直しなさい。

条件もダメダメだし。(sed7sってなんだよ。'が閉じてねーぞ)
> ファイルに ID,ファイル名,1,sed7s/(正規表現)正規表現/正規表現/',と並べてます
0173名無しさん@お腹いっぱい。2006/10/18(水) 20:25:31
cshの環境で、アプリケーションログを
/backup/apl -mtime +6 -exec rm {} \;
上記のようい週次バックアップしています。

これを、直近のデータのみリストアする場合、
(最新のデータのみで、あとはいらない)
どのような表現を使えばいいのでしょうか?

0174名無しさん@お腹いっぱい。2006/10/18(水) 21:20:47
>>170
それでできるはず。ちゃんとbash使ってる?
0175名無しさん@お腹いっぱい。2006/10/18(水) 22:02:08
170のやり方だと

for keyword in "$UNIQ"

でそもそも複数行一括で処理するような気がする
0176名無しさん@お腹いっぱい。2006/10/18(水) 22:04:51
おまえら、もう一度 "$hoge" と $hoge の違いを復習汁。
0177名無しさん@お腹いっぱい。2006/10/19(木) 03:50:14
過去ログを参行にもう一度挑戦しました

file
--------------------------------------------------
hoge:0:
hoge:1:sed "s/a\\(b\\)c\\(de\\)f/x\\1y\\2z/":
hoge:1:sed 's/a\(b\)c\(de\)f/x\1y\2z/':
-------------------------------------------------

hoge
------------------------------------------------
abcdef
------------------------------------------------

#!/bin/sh

while read LINE ;do
IFS=':'
set -- ${LINE}
FILE=$1
SW=$2
CMD=$3
case $SW in
"0" )
echo HOGE ;;
"1" )
cat $FILE | $CMD >hogehogehoge;;
esac
done <file
0178名無しさん@お腹いっぱい。2006/10/19(木) 03:51:43
sh -x ./hogehoge
+ read LINE
+ IFS=:
+ set -- hoge 0
+ FILE=hoge
+ SW=0
+ CMD=
+ case $SW in
+ echo HOGE
HOGE
+ read LINE
+ IFS=:
+ set -- hoge 1 'sed "s/a\(b\)c\(de\)f/x\1y\2z/"' ' '
+ FILE=hoge
+ SW=1
+ CMD='sed "s/a\(b\)c\(de\)f/x\1y\2z/"'
+ case $SW in
+ cat hoge
+ 'sed "s/a\(b\)c\(de\)f/x\1y\2z/"'
./hogehoge: line 13: sed "s/a\(b\)c\(de\)f/x\1y\2z/": No such file or directory
0179名無しさん@お腹いっぱい。2006/10/19(木) 03:52:19
+ read LINE
+ IFS=:
+ set -- hoge 1 'sed '\''s/a(b)c(de)f/x1y2z/'\''' ' '
+ FILE=hoge
+ SW=1
+ CMD='sed '\''s/a(b)c(de)f/x1y2z/'\'''
+ case $SW in
+ cat hoge
+ 'sed '\''s/a(b)c(de)f/x1y2z/'\'''
./hogehoge: line 13: sed 's/a(b)c(de)f/x1y2z/': No such file or directory
+ read LINE
+ IFS=:
+ set --
+ FILE=
+ SW=
+ CMD=
+ case $SW in
+ read LINE
0180名無しさん@お腹いっぱい。2006/10/19(木) 03:53:51
このようなメッセージが出て先に進みません(T-T)
どう改善すればよいのでしょうか

./hogehoge: line 13: sed "s/a\(b\)c\(de\)f/x\1y\2z/": No such file or directory
0181名無しさん@お腹いっぱい。2006/10/19(木) 11:10:31
>>180
そのエラーメッセージの意味がわかるように中学からやり直す。
0182名無しさん@お腹いっぱい。2006/10/19(木) 11:22:15
./ほげほげ: 13番線: sed "s/a\(b\)c\(de\)f/x\1y\2z/": 番号、そのようなやすり、さもなければ登録簿。

訳してみましたが、意味がわかりません。
0183名無しさん@お腹いっぱい。2006/10/19(木) 12:18:27
ここがおかしいのはりかいできるのですが・・・

cat $FILE | $CMD >hogehogehoge;;

$CMDの部分に実行できるコマンドを代入するほうほうはないでしょうか?

0184名無しさん@お腹いっぱい。2006/10/19(木) 12:38:08
>>183
お約束の、catが無駄です。
0185名無しさん@お腹いっぱい。2006/10/19(木) 12:41:53
「sed "s/a\(b\)c\(de\)f/x\1y\2z/"」という名前のコマンドを実行しようとして
ないと言っているのがそのエラーメッセージ。

「sed」コマンドに引数「"s/a\(b\)c\(de\)f/x\1y\2z/"」を与えるのがやりたい
ことだろうがそうはなっていないわけだ。

で、どうしてそういうことになってるかは >>162 で引用されているシェルの
マニュアルの単語分割のところをよく読め。特にお前さんの場合はIFSを
いじっているのでそこらへんも効いている。

0186名無しさん@お腹いっぱい。2006/10/19(木) 14:15:13
>>183
eval はどうよ
0187名無しさん@お腹いっぱい。2006/10/19(木) 14:32:12
>>186
よくわからずに eval 使うより
>>185 あたりを理解するのが先だな。
0188名無しさん@お腹いっぱい。2006/10/19(木) 23:37:29
ShellScript
  
  ↓ 日本語訳

 貝???
0189名無しさん@お腹いっぱい。2006/10/20(金) 02:09:28
>>185 >>186 IFSをループの外にしてevalでSolaris環境では解決しました。

ありがとう。 Cygwinでは改行コードで怒られます。

#!/bin/sh

IFS=','
while read FILE SW CMD
do

case $SW in
"0" )
echo HOGE ;;
"1" )
cat $FILE | eval $CMD >hogehogehoge;;
esac
done <file

file
-------------------
hoge,0,
hoge,1,sed 's/a\\(b\\)c\\(de\\)f/x\\1y\\2z/',
-------------------

hoge
--------------------
abcdef
------------------
hogehogehoge
------------------
xbydez
-------------------
0190名無しさん@お腹いっぱい。2006/10/20(金) 02:12:15
>>184 catが無駄というのは$CMD $FILE >hogehogehoge
という事でしょうか。
0191名無しさん@お腹いっぱい。2006/10/20(金) 08:31:26
>>190
ちょっと違います。
0192名無しさん@お腹いっぱい。2006/10/20(金) 09:37:21
>>190
かなり違います。
0193名無しさん@お腹いっぱい。2006/10/20(金) 11:11:24
>>190
つ <
0194名無しさん@お腹いっぱい。2006/10/20(金) 15:21:56
$FILEにファイル名が複数入っている可能性があるのならそのcatもあながち
無駄ではないかもしれない。
0195名無しさん@お腹いっぱい。2006/10/20(金) 16:21:00
>>194
その可能性はあり得ない。
>>189
while read FILE SW CMD

って書いてるから。よってやはり「catが無駄です」
0196名無しさん@お腹いっぱい。2006/10/21(土) 18:07:53
catが無駄かどうかがこんなに盛り上がるとは。
0197名無しさん@お腹いっぱい。2006/10/21(土) 19:36:02
freebsd の sleep 議論ってやつやね
0198名無しさん@お腹いっぱい。2006/10/23(月) 04:40:19
シェルスクリプトって便利で好きだけど、限度があるからperlに逃げる。
シェルスクリプトならでは、という美しいサンプルはどの辺に行けば見れますか?
0199名無しさん@お腹いっぱい。2006/10/23(月) 06:36:28
/etc/init.d
0200名無しさん@お腹いっぱい。2006/10/23(月) 08:28:02
シェルスクリプトは美しさを求めるもんじゃないと思う。
0201名無しさん@お腹いっぱい。2006/10/23(月) 11:14:52
工エエェェ(´д`)ェェエエ工
0202名無しさん@お腹いっぱい。2006/10/23(月) 13:45:43
シェルスクリプトならではのねじれ曲がったサンプルなら./configure
0203名無しさん@お腹いっぱい。2006/10/23(月) 16:20:35
Linuxの~/.bashrcに

unalias vi

という行を追加しました。というのは、ディフォルトのviだと、文字が緑ではなく、いろんな色でカラフルに
表示されるので、unaliasしてみたら、緑一色で表示できたので。
これでviは快適に使えるようになったのですが、別の問題が起こりました。
それは、bashを起動して別のシェルを動かした場合に.bashrcがもう一度実行されるので、
既にviはunaliasされているにもかかわらず、再度unaliasしようとして以下の警告が表示されます。

bash: line 49: unalias: vi: not found

警告が出ても、処理は問題なくできるので、気にしなければ、いいのですが、
でも気になるので、何か良い解決方法を教えてください
よろしく。
0204名無しさん@お腹いっぱい。2006/10/23(月) 16:42:00
>>203
単に
alias vi=
の行を.bashrcから削除すりゃいいのでは、と思ったが、
/etc/のどこかで定義されてるのかねぇ。

alias | grep '^alias vi=' >/dev/null && unalias vi
0205名無しさん@お腹いっぱい。2006/10/23(月) 16:44:52
alias して unalias すればいーじゃん
0206名無しさん@お腹いっぱい。2006/10/23(月) 16:46:31
>>203
~/.bash_profile に書けば?
0207名無しさん@お腹いっぱい。2006/10/23(月) 16:48:11
ちっともシェルスクリプトじゃない。
0208名無しさん@お腹いっぱい。2006/10/23(月) 16:49:48
だな。
続きはこっちで。

くだらねえ質問はここに書き込め! Part 133
http://pc8.2ch.net/test/read.cgi/linux/1160894184/
0209名無しさん@お腹いっぱい。2006/10/23(月) 16:53:27
>>205
お前頭いいな
0210名無しさん@お腹いっぱい。2006/10/23(月) 18:12:39
>>205
それするくらいなら、
unalias vi 2> /dev/null
でいいじゃん。メッセージを捨てるだけ。
0211名無しさん@お腹いっぱい。2006/10/23(月) 18:44:40
>206
この方法で解決しました。
ありがとございます。
0212名無しさん@お腹いっぱい。2006/10/24(火) 10:14:07
遅レスだが
>>165
> zsh だと、$hoge2 と書いても "$hoge2" と同じに解釈される糞仕様なので、、、
setopt SH_WORD_SPLIT あるいは明示的に${=hoge2}とする。
0213名無しさん@お腹いっぱい。2006/10/25(水) 16:35:32
第一フィールドがmm/dd/yyyy
第二フィールドがhh:mm:ss
第三フィールドが""で囲まれたアカウント名

となっている。
「アカウント名が重複しているものは、その最新日付のみを残して、
他の重複行はすべて削除」
という具合にしたい。

uniqを使えばいいのかもわからないが、やっぱりわからない。
どうすればいいだろう。

08/11/2006 14:29:50 "yamamoto"
03/03/2006 06:40:53 "yamada"
05/17/2005 07:45:07 "yamada"
07/13/2005 04:18:04 "yamada"
07/13/2005 13:17:56 "yamada"
08/04/2005 11:03:05 "yamada"
08/11/2005 05:54:56 "yamada"
08/11/2004 07:58:53 "yamada"
12/07/2005 13:54:19 "yamada"
12/22/2005 00:26:49 "yamada"
08/05/2005 02:48:41 "kinosita"
08/05/2005 11:49:58 "kinosita"
08/05/2004 11:51:45 "kinosita"
08/06/2005 04:55:50 "kinosita"
02/21/2005 16:34:40 "akie"
02/21/2006 17:20:21 "akie"
02/21/2006 17:22:56 "akie"
02/21/2005 17:41:45 "akie"
02/21/2005 17:47:14 "akie"
0214名無しさん@お腹いっぱい。2006/10/25(水) 16:40:07
>>213
こんなんシェルスクリプトでやりたくないな。
perl かなんかで。
0215名無しさん@お腹いっぱい。2006/10/25(水) 16:43:13
連想配列使える言語(awk, perl, csh)を使わない理由は?
0216名無しさん@お腹いっぱい。2006/10/25(水) 16:54:59
>>213
シェルで簡単にできるよ。
ちょっとパイプが多段だけど。


while read dt tm user
do
echo $dt $tm `date +%s -d "$dt $tm"` $user
done | sort -nr | uniq -3 | while read dt tm sec user
do
echo $dt $tm $user
done


ポイントは、dateで単純な秒数に変換する前処理をしてから
フィールドスキップして uniq すること。
その後で秒数フィールドを削除して元に戻してる。

GNU dateが必要かも知れない。

perl とか 連想配列とか言ってる香具師は弱もの。
0217名無しさん@お腹いっぱい。2006/10/25(水) 16:59:54
弱ものってなんだろ。
0218名無しさん@お腹いっぱい。2006/10/25(水) 17:04:25
どうもです。
perlなどでやったほうがお手軽なんですね。
覚えがあるのがshellだけなので、やむをえず・・・。

Cygwinじゃdate -dでエラーになるので、FreeBSDで試してみます。
0219名無しさん@お腹いっぱい。2006/10/25(水) 17:08:53
>GNU dateが必要かも知れない。
こんな俗物に頼る方が、頭がヨワイ。
0220名無しさん@お腹いっぱい。2006/10/25(水) 17:13:42
>>219
08/11/2006 14:29:50
を、
2006/08/11 14:29:50
に変換する前処理を入れれば、
date使わなくても >>216 の方法で行けるよ。

>>216 って短時間に良くこんなシェルスクリプト組めますね。
さてはかなりのプロと見た。
0221名無しさん@お腹いっぱい。2006/10/25(水) 17:33:44
>>216
>done | sort -nr | uniq -3 | while read dt tm sec user

sort -k 3 -nrだろう
0222名無しさん@お腹いっぱい。2006/10/25(水) 17:36:56
>>221
まちがえた
0223名無しさん@お腹いっぱい。2006/10/25(水) 17:37:14
>>216
それだと名前の順序が変わるから
> その最新日付のみを残して、他の重複行はすべて削除
を満たさない。
それと、uniq ではスキップするフィールドを指定するんだから uniq -2 だし、
uniq が削除するのは連続した場合だから名前フィールドでの sort も必要。
0224名無しさん@お腹いっぱい。2006/10/25(水) 17:38:32
>>223
いや、uniq -3 は合ってるよ。1フィールドを追加してるから。
0225名無しさん@お腹いっぱい。2006/10/25(水) 17:41:18
>>224
あ、そうか。ゴメン。
0226名無しさん@お腹いっぱい。2006/10/25(水) 17:44:00
date で追加するフィールドを頭に持ってきて、
sort -nr | uniq -3 で最新日付だけ残して
最後に頭のフィールドを削除するのが奇麗だな。
0227名無しさん@お腹いっぱい。2006/10/25(水) 17:46:13
>>226
頭のフィールドはuserだろう
■ このスレッドは過去ログ倉庫に格納されています