2ちゃんねる スマホ用 ■掲示板に戻る■ 全部 1- 最新50    

■ このスレッドは過去ログ倉庫に格納されています

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

1 :名無しさん@お腹いっぱい。:2014/07/01(火) 17:55:50.75 .net
シェルスクリプトの総合スレです。
□お約束
・特記なき場合は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に逃げずにシェルスクリプトで処理するのが頭のいいやり方。
前スレ
シェルスクリプト総合 その22
http://peace.2ch.net/test/read.cgi/unix/1383260330/

951 :名無しさん@お腹いっぱい。:2014/10/23(木) 05:32:28.62 .net
>>950
()で囲うだけで配列にできるのですね。

results=("$(コマンド)")
ダブルクォーテーションで囲えば空白を含む場合も問題ないですね。

とてもシンプルになりました。
ありがとうございました。

952 :名無しさん@お腹いっぱい。:2014/10/23(木) 05:50:14.41 .net
>>951
> results=("$(コマンド)")
> ダブルクォーテーションで囲えば空白を含む場合も問題ないですね。
勘違いしていました。
これだと配列の要素が1つだけでだめですね。

953 :名無しさん@お腹いっぱい。:2014/10/23(木) 06:23:00.43 .net
あるコマンドの出力結果の各行が要素となる配列を作りたい。
出力行にスペースを含まない場合は >>950 のように()で囲めばいい。
スペースを含む場合は >>948 のようにやる必要がある。

ということみたいですかね。
たいへんお騒がせしました。

954 :名無しさん@お腹いっぱい。:2014/10/23(木) 06:38:12.59 .net
>>953
>>948 のようにやる必要はない。
改行を IFS として >>951 みたいにやればいいだけ

955 :名無しさん@お腹いっぱい。:2014/10/23(木) 06:41:57.64 .net
>>953
IFS='
' list=(`ls -l`)


これでls -l の各行ごとに配列要素に入る。IFS変更してることに注意。

956 :名無しさん@お腹いっぱい。:2014/10/23(木) 06:52:10.33 .net
>>954,953
なるほど。
処理が終わったらIFSを元に戻せばいいですし、これでいけますね。

シェルがおもしろくなってきましたw
ありがとうございました。

957 :名無しさん@お腹いっぱい。:2014/10/24(金) 09:46:02.92 .net
bashの配列もいいけど、>>914,913,916が無かったかの様に進んでいくのが残念なので一言

もともと for 文も変数をインクリメントしてループする様には出来ていない for in (foreach) 文だし、
シェルスクリプトでは、改行区切りで配列のようにデータを扱うのが素直なやり方だと思うのだが、どうだろうか?

#!/bin/sh
LF='
'
exec 3<&0 0< input.txt
while
 IFS=$LF read line
do
 echo "$line"
done
exec 0<&3 3<&-


IFS_BKUP=$IFS
IFS=$LF
for line in $( ls -l )
do
 echo "$line"
done
IFS=$IFS_BKUP

958 :名無しさん@お腹いっぱい。:2014/10/24(金) 13:01:25.31 .net
よくわからんが俺なら、cut -d: -f1 /etc/passwd するね

959 :名無しさん@お腹いっぱい。:2014/10/24(金) 13:54:52.89 .net
お前は何を言ってるんだw

960 :名無しさん@お腹いっぱい。:2014/10/24(金) 14:24:22.48 .net
>>958
直前までデータのまとめ方の話だったけど、その話では無かったつもりだった
紛らわしく書いてしまったみたいだ

変数に入れるなり、ファイルにするなりしても、大抵は配列は特に必要なく、
改行区切りのデータのまま扱うのがシェルスクリプトらしいかと、い痛かった

#!/bin/sh
exec < /etc/passwd

users=$(
 #cut -d: -f1
 while
  IFS=: read user trash
 do
  echo "$user"
 done
)

IFS='
'
for user in $users
do
 echo "$user"
done

961 :名無しさん@お腹いっぱい。:2014/10/30(木) 00:56:19.87 .net
ミドルウェアのインストーラ(シェルスクリプト内)に
uuencode/uudecodeで巨大なファイルを埋め込んでるのがあったんだが
スクリプト内にファイルを仕込むことで、何か特別な意味あったりするの?

メモリが足りなくなって、インストーラがコケまくるし
再実行するたびにデコードして展開するから胸糞悪かった

962 :名無しさん@お腹いっぱい。:2014/10/30(木) 03:42:14.29 .net
シェルスクリプトで全部配布出来る、とか。

963 :名無しさん@お腹いっぱい。:2014/10/30(木) 05:28:34.84 .net
Windowsっぽくしたかったんじゃね。

964 :名無しさん@お腹いっぱい。:2014/10/30(木) 05:39:51.98 .net
uuencodeなだけいいじゃないか。
javaのインストーラなんて直接バイナリ埋め込んでるし。
シェルスクリプトをexitで終了すればexit以降の部分がバイナリでもOKという技。
tail -n +行 でバイナリ切り出して解凍、みたいな。

965 :名無しさん@お腹いっぱい。:2014/10/30(木) 13:37:12.47 .net
>>961
実行するだけでインストールできるから楽でしょ
この間インストールしたjava(jdk)もその形式だったし

966 :名無しさん@お腹いっぱい。:2014/11/09(日) 18:06:16.96 .net
もう10日書き込みなしか
でもみんな見てはいるんだろうなと予想

967 :名無しさん@お腹いっぱい。:2014/11/09(日) 18:50:24.89 .net
では、以下のより善い最適な正解を考えよう

http://hello.2ch.net/test/read.cgi/morningcoffee/1408885443/924
> 924 名前:名無し募集中。。。@転載は禁止 []: 2014/11/06(木) 22:56:57.47 0
> いくつもtar.gzがあるときにどのtar.gzにMakefileが入ってるか探そうと思ったらこんな感じ?
>  tar -xzf *.tar.gz
>  find ./ -name Makefile
> でもこれだとフォルダ名が被った時に上書きされてしまう・・・もっとうまいシェルあるかな?

> 927 名前:名無し募集中。。。@転載は禁止 []: 2014/11/06(木) 23:33:24.12 0
> bash以外で使えるかは知らないけど
> find -name "*.tar.gz" | while read ; do (echo " -- $REPLY ---" ; tar -tf "$REPLY" | grep Makefile) done

> 928 名前:名無し募集中。。。@転載は禁止 []: 2014/11/06(木) 23:58:28.48 0
> shだとこんな感じで動きそう
> find . -name "*.tar.gz" | while read REPLY; do (echo " -- $REPLY ---" ; tar -tf "$REPLY" | grep Makefile) done

968 :名無しさん@お腹いっぱい。:2014/11/09(日) 18:59:36.73 .net
>>967
zgrep -l Makefile *.tar.gz
で一発。

969 :名無しさん@お腹いっぱい。:2014/11/09(日) 21:01:40.56 .net
>>966
専ブラで見てるから書き込みが無いと見ないんだな・・・
正直なところココに書き込むか他の質問スレに書き込むか迷って
他に書き込むことはある

970 :名無しさん@お腹いっぱい。:2014/11/09(日) 21:22:13.32 .net
>>968
それではサブディレクトリ以下の*.tar.gzを検索しない

971 :名無しさん@お腹いっぱい。:2014/11/09(日) 22:38:09.71 .net
zgrep -l Makefile **/*.tar.gz

972 :名無しさん@お腹いっぱい。:2014/11/09(日) 22:43:36.52 .net
>>971
カレントディレクロリの*.tar.gzを検索しなくなった

973 :名無しさん@お腹いっぱい。:2014/11/09(日) 23:58:58.66 .net
ロリ…

974 :名無しさん@お腹いっぱい。:2014/11/10(月) 00:04:45.26 .net
ディレクトロリ

975 :名無しさん@お腹いっぱい。:2014/11/10(月) 00:22:06.71 .net
いくつもあるとしか言ってないから、そういう場合は大抵、ひとつのディレクトリで十分だと思うな。

976 :名無しさん@お腹いっぱい。:2014/11/10(月) 00:49:17.58 .net
まあ何にせよ、現状は
find . -name "*.tar.gz" | while read REPLY; do (echo " -- $REPLY ---" ; tar -tf "$REPLY" | grep Makefile) done
最強だな。
サブディレクトリの*.tar.gz全ても、*.tar.gzの中のリストも
表示される

977 :名無しさん@お腹いっぱい。:2014/11/10(月) 01:11:31.68 .net
>>972
はい、ごめんなさい

>>976
最強?
並列で動いてるようにすら見えないのだが

978 :名無しさん@お腹いっぱい。:2014/11/10(月) 01:20:38.07 .net
横から見てたけど、結果出すのが強いと思うよ

979 :名無しさん@お腹いっぱい。:2014/11/10(月) 01:25:12.67 .net
>>976
・ファイル名に改行コードが入っていたら?
・"〜.tar.gz" っていう名前のディレクトリがあったら?
・whileの中は { echo ...; tar -tf ...; } でいいんじゃ?(わざわざサブシェルにする理由がワカらん)

980 :名無しさん@お腹いっぱい。:2014/11/10(月) 01:26:05.43 .net
>>978
言い出しっぺの法則って事で
速度度外視でいいからサンプル生成コードを出してくれ

981 :名無しさん@お腹いっぱい。:2014/11/10(月) 01:36:13.41 .net
>>980
俺は「結果出すのが強い」と事実を書いただけだが、何の「言い出しっぺ」なの?

982 :名無しさん@お腹いっぱい。:2014/11/10(月) 01:39:33.45 .net
$ find . -type f -readable -name "*.tar.gz" -print0 | xargs -0 -I'{}' /bin/bash -c 'echo " -- {} ---"; tar -tf "{}" | grep Makefile'

983 :名無しさん@お腹いっぱい。:2014/11/10(月) 01:53:14.13 .net
>>982
横から見てた別人だけど、なるほどそういう方法もあるんですね。
ちなみに>>976に対するアドバンテージってナニですか?
>>977のいう並列動作ですか?

984 :名無しさん@お腹いっぱい。:2014/11/10(月) 01:58:22.51 .net
>>976
readは指定しなければREPLYに入れるから冗長。

985 :名無しさん@お腹いっぱい。:2014/11/10(月) 02:03:07.35 .net
>>983
>・ファイル名に改行コードが入っていたら?
>・"〜.tar.gz" っていう名前のディレクトリがあったら?

これ↑に対処。並列動作させる場合は xargs に -P0 を付けるとよろし

986 :名無しさん@お腹いっぱい。:2014/11/10(月) 02:19:56.10 .net
>>985
なるほど。その対策ですか。

-P0 付けたら表示がバラバラになってしまいますね。

987 :名無しさん@お腹いっぱい。:2014/11/10(月) 02:28:00.33 .net
ファイルの順序はバラバラになるけど、Makefileが含まれているかどうか
が判れば良いはずなので問題はないと思う。ファイルの表示順序を維持
したい場合は GNU parallel を使えば良い。オプションはxargsの上位互換
になっている

988 :名無しさん@お腹いっぱい。:2014/11/10(月) 02:40:36.58 .net
GNU Parallel 版

$ find -L . -type f -readable -name "*.tar.gz" -print0 | sort -z | parallel -P 0 -0 -k 'echo " -- {} ---"; tar -tf "{}" 2>/dev/null | grep Makefile'

"-k" オプションが入力順序と出力順序を一致させる(keep order)
それと、find に "-L" オプションを付けて、tar のエラーメッセージを捨てる様にした

989 :名無しさん@お腹いっぱい。:2014/11/10(月) 02:49:17.86 .net
>>981
「結果」なるもの定義が
速度?ゴルフ?動けばいいの?
などとあいまいで分かりづらかったんだよね。
でも本人さんなら「結果出すのが強い」と明確に判断できるような
お題のサンプルぐらいは提示できるひとかなっと思ったんだ
なんだかごめん。

990 :名無しさん@お腹いっぱい。:2014/11/10(月) 05:32:23.44 .net
zgrep -lr Makefile .
一発

991 :名無しさん@お腹いっぱい。:2014/11/10(月) 09:24:03.48 .net
/bin/zgrep: -r: option not supported

992 :名無しさん@お腹いっぱい。:2014/11/10(月) 12:34:39.57 .net
>>989
> 「結果」なるもの定義が

普通に流れ読めばわかるだろ

993 :名無しさん@お腹いっぱい。:2014/11/10(月) 12:54:30.50 .net
dump(ufsdump)形式で固めたアーカイブを、
展開せずに tar (tar.gz)形式に変換したいんだが、
何かいい方法ある?

994 :名無しさん@お腹いっぱい。:2014/11/10(月) 15:03:04.46 .net
>>993
さらに上からtarする。

995 :名無しさん@お腹いっぱい。:2014/11/11(火) 00:56:17.74 .net
次スレ

シェルスクリプト総合 その24?2ch.net
http://peace.2ch.net/test/read.cgi/unix/1415634843/

996 :名無しさん@お腹いっぱい。:2014/11/11(火) 08:23:57.90 .net
>>995


997 :名無しさん@お腹いっぱい。:2014/11/11(火) 14:05:29.13 .net
梅がてら最近のケアレスミスを紹介

wgetでサイトのページ取ってきて解析するスクリプト作ってた
でもたまに解析に失敗する
試しにsleep入れたらちょっとましになったけどやっぱり失敗することがある
処理時間も考慮する必要があるから無駄に30秒とか入れたくないし・・・
でよく見直したら行末に「&」が付いてて非同期処理になってた
経緯としては標準出力&エラーを/dev/nullに叩き込んでたんだけど
いつも使うnohupの処理をそのままパクってきたときに消し忘れてた
これがわかるまでwgetってバッファとかメモリからの書き出しに
ラグがあるのかと思ってたくらいいいorz

998 :名無しさん@お腹いっぱい。:2014/11/11(火) 17:12:33.03 .net
URLのをクォートせずにコピペしてクエリの&でbgにしてることは、まれによくある。
クエリにコマンドしこまれてたら、セキュリティホールだな。区切り文字となるスペースないから、大したことできないかもだけど。

999 :名無しさん@お腹いっぱい。:2014/11/11(火) 17:35:57.09 .net
>>998
あるあるw

ちなみに、特殊文字を含むデータをペーストしようとすると警告してくれる端末エミュレータが
あった気がする。TeraTerm だったかなあ? あの機能には助けられた覚えがある。

1000 :名無しさん@お腹いっぱい。:2014/11/11(火) 18:29:25.62 .net
Xの端末は腐ったときに表示した文字をコマンドとしてシェルが実行してしまうことがあるよねw

総レス数 1000
252 KB
掲示板に戻る 全部 前100 次100 最新50
read.cgi ver 2014.07.20.01.SC 2014/07/20 D ★