シェルスクリプト総合 その19
■ このスレッドは過去ログ倉庫に格納されています
0001シェルスクリプトライター
2011/12/10(土) 20:06:40.38スクリプトのお勉強・自慢・腕試しなどにどうぞ。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
Linuxユーザは/bin/shの正体がbashなので特に注意。
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でそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
前スレ
シェルスクリプト総合 その18
http://hibari.2ch.net/test/read.cgi/unix/1308195527/
次スレは >>970 で。
0102名無しさん@お腹いっぱい。
2012/01/08(日) 17:51:50.20自演乙 おちつけ
date +%Y-%m | sed 's/-0//; s/-//'
0103名無しさん@お腹いっぱい。
2012/01/08(日) 17:58:24.55おぉ、もう返答が。
そうか、消したい0の前に何か付け足すことで限定すれば良いんですね。
ありがとうございました。
0104名無しさん@お腹いっぱい。
2012/01/08(日) 18:03:08.42せっかくbashならdateコマンド以外、内部コマンドだけでもできるよ。
a=($(date +'%Y %m'))
echo ${a[0]}${a[1]#0}
0105名無しさん@お腹いっぱい。
2012/01/08(日) 18:57:49.32case $month in
0?) month=${month##0} ;;
esac
lm=`date +%Y$month`
or if you are using GNU date
date +%Y%-m
0106名無しさん@お腹いっぱい。
2012/01/08(日) 19:15:43.51>>105 最終行の
date +%Y%-m
が最適解だな。
ところで、>>105 前半のcase文は意味ない。場合分けせずに ${month#0}だけでよい。
0107名無しさん@お腹いっぱい。
2012/01/08(日) 19:52:34.83man dateで>>105さんのやり方がしっかり書いてありました…
お恥ずかしい。
皆様ありがとうございます。
0108名無しさん@お腹いっぱい。
2012/01/08(日) 22:51:02.00今まで expr で 0 を消してた。
0109名無しさん@お腹いっぱい。
2012/01/09(月) 08:29:51.48echo $(date +%Y)$(expr $(date +%m) + 0)
0110名無しさん@お腹いっぱい。
2012/01/09(月) 08:53:59.96expr `date +%m` : "0\?\(.\+\)"
0111名無しさん@お腹いっぱい。
2012/01/09(月) 09:00:41.79$ echo $((08+0))
-bash: 08: value too great for base (error token is "08")
0112名無しさん@お腹いっぱい。
2012/01/09(月) 09:08:48.76シェルの算術式とかでは頭の0は8進数扱いだからな。
exprなら8進数とはみなさないので、expr 08 + 0 とかやって0を消すのは常識テクニック。
0113名無しさん@お腹いっぱい。
2012/01/13(金) 10:37:37.37sed -e "s/ //g" temp.txt
↑ここに/(スラッシュ)を含む文字列を入れたいときはどうしたらいんですか?
0114名無しさん@お腹いっぱい。
2012/01/13(金) 10:46:55.510115名無しさん@お腹いっぱい。
2012/01/13(金) 11:12:47.98>>114のようにするか、区切り文字を"/"から"@"とかの他の文字に変える
純粋なsedの話しなのでスレち
ttp://toro.2ch.net/test/read.cgi/unix/1085730992/
0116名無しさん@お腹いっぱい。
2012/01/19(木) 17:43:20.44中間ファイルを作ってディレクトリ名と日付の比較を行なっての処理は一応出来たのですが、出来ればfind xargsで一発で出来る形にしたいです
中間ファイル無しで上記のような処理は実現できるでしょうか?
0117名無しさん@お腹いっぱい。
2012/01/19(木) 17:54:34.58yyyymmddHHMMSS形式なら単純な数値と考えて大小比較すればいいね。
比較するのに中間ファイルは要らない。
0118名無しさん@お腹いっぱい。
2012/01/19(木) 18:05:56.97エスパーカが足りないなw
中間ファイルは条件にマッチしたディレクトリリストのファイルかと
tarじゃなくてcpioなら Solaris findの -cpioオプションで一発かな
0119名無しさん@お腹いっぱい。
2012/01/19(木) 18:35:22.450120名無しさん@お腹いっぱい。
2012/01/19(木) 18:52:00.33-newer のたぐいはまさに中間ファイルが必要ですが
0121名無しさん@お腹いっぱい。
2012/01/19(木) 18:56:59.650122名無しさん@お腹いっぱい。
2012/01/19(木) 19:01:28.69どんな内容の中間ファイルをどのような目的で作成しているのか
それがわかれば回答する側もエスパーにならなくていいからね
0123名無しさん@お腹いっぱい。
2012/01/19(木) 19:02:52.930124名無しさん@お腹いっぱい。
2012/01/19(木) 19:04:30.79どうやって?
0125名無しさん@お腹いっぱい。
2012/01/19(木) 23:32:23.93/home/my/st/1.txt
1 暑い
2 寒い
3 少し暑い
4 少し寒い
5 すごく暑い
6 すごく寒い
/home/my/st/2.txtに書き込ませたいですのですがどう書けば良いでしょうか?
0126名無しさん@お腹いっぱい。
2012/01/19(木) 23:50:32.460127名無しさん@お腹いっぱい。
2012/01/19(木) 23:57:33.44わお
そんなに短く出来るんですね
感謝です!!
0128名無しさん@お腹いっぱい。
2012/01/20(金) 00:02:25.13調べたらこんな感じにもできそうだった。
shuf --rndom-source=1.txt -o 2.txt
0129名無しさん@お腹いっぱい。
2012/01/20(金) 00:34:25.58--random-source=/dev/random
--random-source=/dev/zeroで試してみて
0130名無しさん@お腹いっぱい。
2012/01/20(金) 01:03:57.15全行シャッフルとかしなくていいのがメリットだとか。
perl -ne '$result = $_ if rand($.)<1; END{print $result}'
0131名無しさん@お腹いっぱい。
2012/01/20(金) 01:24:54.340132名無しさん@お腹いっぱい。
2012/01/20(金) 06:30:44.02catもパイプも無駄だな。
shuf -n 1 < 1.txt > 2.txt
0133名無しさん@お腹いっぱい。
2012/01/20(金) 08:44:30.170134名無しさん@お腹いっぱい。
2012/01/20(金) 11:04:53.930135名無しさん@お腹いっぱい。
2012/01/20(金) 13:37:16.040136名無しさん@お腹いっぱい。
2012/01/20(金) 13:55:53.73POSIXにはない
0137名無しさん@お腹いっぱい。
2012/01/20(金) 19:02:11.53へどらとかならあるんじゃね?
0138名無しさん@お腹いっぱい。
2012/01/20(金) 19:09:47.870139名無しさん@お腹いっぱい。
2012/01/20(金) 19:11:08.120140名無しさん@お腹いっぱい。
2012/01/20(金) 19:58:46.800141名無しさん@お腹いっぱい。
2012/01/20(金) 22:33:57.03大手SIerじゃ5年前から常識だな
0142名無しさん@お腹いっぱい。
2012/01/20(金) 23:18:45.090143名無しさん@お腹いっぱい。
2012/01/20(金) 23:39:27.25A="`cat list.txt |tr -s \\n , |head -c -1`"
でもこれだとnが,に置換される。\\nを'\n'にすればいけたけど、バッククオートの中のエスケープって何回評価されるの?
0144名無しさん@お腹いっぱい。
2012/01/21(土) 00:28:29.06\n
0145名無しさん@お腹いっぱい。
2012/01/21(土) 01:02:25.99ユーザーアカウント名とパスワードを自動で入れてログインしたいのですが
0146名無しさん@お腹いっぱい。
2012/01/21(土) 02:12:35.16http://linuxjm.sourceforge.jp/html/GNU_bash/man1/bash.1.html#lbBA
A="$(cat list.txt |tr -s \\n , |head -c -1)"
0147名無しさん@お腹いっぱい。
2012/01/21(土) 07:43:37.27とりあえずcatが無駄。
バッククオートの中のバックスラッシュは特殊な意味を持つので、
2回評価されると考えとけばいい。
この例ではバックスラッシュ3回で回避できる。
>>146
$( )使っちゃ駄目よ。
0148名無しさん@お腹いっぱい。
2012/01/21(土) 08:02:20.86なぜ cat をわざわざ付けるかと言うと、
自分が作る全てのスクリプトや打ち込むコマンドで
ファイルを読む際には必ず cat で読む
と統一する事で、ミスる可能性を減らしてるつもり。
客に納品するスクリプトでは仕方なく削るけど。
元々のきっかけは 20 年程前に tar でファイル消してしまったことだった。
0149名無しさん@お腹いっぱい。
2012/01/21(土) 08:09:55.160150名無しさん@お腹いっぱい。
2012/01/21(土) 08:51:51.18コメントの様な物だ。
0151名無しさん@お腹いっぱい。
2012/01/21(土) 08:55:23.20の順に書きたいというだけの理由なら、
< file コマンド
と書けば良い。
0152143
2012/01/21(土) 09:25:54.14凄く参考になった。ありがとう
> バッククォートを使う古い形式の置換を用いたとき、バックスラッシュは文字通りの意味を保ちます
> が、 $, `, \ の前にある場合は例外となります。バックスラッシュが前置されていないバッククォートが
> あると、そこでコマンド置換は閉じられます。 $(command) という形式を用いたときは、括弧の間にある
> 全ての文字がコマンドとなります。特別扱いされる文字はありません。
`cmd`と$(cmd)の2つの形式で意味(処理?)が違うなんて知らなかった
> コマンド置換は入れ子にできます。バッククォート形式の時に入れ子を行うには、
> 内側のバッククォートをバックスラッシュでエスケープします。
入れ子にするときは2つの形式を組み合わせて書いてたから、これも気が付かなかった
特殊扱いの文字が$(cmd)形式ではないなら、cmdの中に)がある場合\でエスケープはできないってことか
>>147
評価回数について、ありがとう。最小3つ並べる必要があるのか
cat使っているのは、前処理があってパイプを使っているという意思表示
ときどきシーク可能か否かで挙動が変わるプログラムもありますし
0153名無しさん@お腹いっぱい。
2012/01/21(土) 10:01:25.74> $( )使っちゃ駄目よ。
爺さんや、Solarisでも/bin/shはkshになりましたよ。
というわけでもういいんじゃないか。テンプレもそろそろ修正どき。
0154名無しさん@お腹いっぱい。
2012/01/21(土) 10:17:31.18正直、その書き方は知らなかった。
0155名無しさん@お腹いっぱい。
2012/01/21(土) 10:26:19.10同じ様な経験から自分と似たような対処している全然知らない人の存在を知ると、何か和むなぁ
0156名無しさん@お腹いっぱい。
2012/01/21(土) 10:28:50.430157名無しさん@お腹いっぱい。
2012/01/21(土) 11:57:08.26なんかずれてる気がする
0158名無しさん@お腹いっぱい。
2012/01/21(土) 12:16:06.97tar xvf と tar cvf を間違えたって話か?
ふつーあらかじめ chmod -w hoge.tar やっておくから消すことはありえない。
0159名無しさん@お腹いっぱい。
2012/01/21(土) 12:33:47.900160名無しさん@お腹いっぱい。
2012/01/21(土) 13:25:25.150161名無しさん@お腹いっぱい。
2012/01/21(土) 13:29:30.84とやろうとして
tar cvf bbb ccc
とかやって、bbbを消しちゃったってことかな
0162名無しさん@お腹いっぱい。
2012/01/21(土) 13:32:21.940163名無しさん@お腹いっぱい。
2012/01/21(土) 14:11:25.85>>146 では「ファイルを読む際には必ずcatで読む」て言ってるから、
tar xvf の時の話かと。
0165名無しさん@お腹いっぱい。
2012/01/22(日) 00:51:01.40cat foo | cmd1
で、cmd1の前に前処理やりたくなった時、
cat foo | cmd0 | cmd1
と書き換え簡単。
cmd1 fooをcmd0 foo | cmd1にするのは語順置き換えがある。
transpose-wordするのは空白入り"文字列やオプション指定があるとちょっと面倒。
ファイル名をひとつしか指定できないバカコマンドで、
2つ指定したくなった時にイラっとくるから、などの理由。
0166名無しさん@お腹いっぱい。
2012/01/22(日) 01:25:14.86ファイルがないなどのエラーを捕捉し損ねる可能性があるから。
0167名無しさん@お腹いっぱい。
2012/01/22(日) 06:46:04.290168名無しさん@お腹いっぱい。
2012/01/22(日) 08:04:14.62cat foo | cmd1 ではなく、
< foo cmd1 とする。(いつもこう書く癖を付けておく)
で、cmd1の前に前処理やりたくなった時、
< foo cmd1 | cmd2
と書き換え簡単。
以上で、catを無駄に使う理由がなくなる。
0169名無しさん@お腹いっぱい。
2012/01/22(日) 09:05:11.75(| (< foo cmd1) cmd2)
とかって書くやつ
0170名無しさん@お腹いっぱい。
2012/01/22(日) 10:15:08.87流れが一方向ではないので理解しづらい。
そもそも<禁止ルールがある場合もある。
0171名無しさん@お腹いっぱい。
2012/01/22(日) 10:19:18.34俺ルールでは禁止って後だしで言われてもなあ。 w
0172名無しさん@お腹いっぱい。
2012/01/22(日) 10:30:20.87良く見ろ。流れは一方向だぞ。
流れを一方向にするために、
com1 < file | com2
を
< file com1 | com2
と並べ変えたんだが。>>170 は良く読んでなさそうだなw
0173名無しさん@お腹いっぱい。
2012/01/22(日) 11:00:43.73初心者でも読めるように cat から始めろ。
実績がないから cat から始めろ。
俺流を通す無能な上司を説得する方法も教えろください。
0174名無しさん@お腹いっぱい。
2012/01/22(日) 11:05:03.14> で、cmd1の前に前処理やりたくなった時、
> < foo cmd1 | cmd2
逆じゃね?
0175名無しさん@お腹いっぱい。
2012/01/22(日) 11:16:14.220176名無しさん@お腹いっぱい。
2012/01/22(日) 11:16:49.44で、cmd1の前に前処理やりたくなった時、
< foo cmd0 | cmd1
かな
0177名無しさん@お腹いっぱい。
2012/01/22(日) 11:22:49.700178名無しさん@お腹いっぱい。
2012/01/22(日) 11:30:36.380179名無しさん@お腹いっぱい。
2012/01/22(日) 11:38:12.780180名無しさん@お腹いっぱい。
2012/01/22(日) 11:43:57.77引用レスの最初に入力リダイレクト書くと顔文字みたい > <
0181名無しさん@お腹いっぱい。
2012/01/22(日) 12:11:08.982>&1とか使うくらいならcshでやれよ頭固いなあ
0182名無しさん@お腹いっぱい。
2012/01/22(日) 12:15:52.47だって、無能上司の部下だもの。
0183名無しさん@お腹いっぱい。
2012/01/22(日) 12:19:51.880184名無しさん@お腹いっぱい。
2012/01/22(日) 12:29:22.980185名無しさん@お腹いっぱい。
2012/01/22(日) 13:05:48.180186名無しさん@お腹いっぱい。
2012/01/22(日) 13:16:17.54< foo cmd1は使えない。
!<でも
!cmd1
でもhistoryを呼び出せない。
0187名無しさん@お腹いっぱい。
2012/01/22(日) 13:21:03.72シェルスクリプトでhistoryを使う馬鹿?
0188名無しさん@お腹いっぱい。
2012/01/22(日) 13:41:56.10全力で己の無能を告白するなよ。ドMの新しいプレーか? www
!?cmd1
で呼び出せるだろ。
0189名無しさん@お腹いっぱい。
2012/01/22(日) 14:22:29.46リダイレクトじゃ複数は無理だし、多く引数を取るコマンド、特に入出力のファイル名を
どちらも引数に取れるコマンドだと、入力だけ区別して分けられる
0190名無しさん@お腹いっぱい。
2012/01/22(日) 14:45:03.840191名無しさん@お腹いっぱい。
2012/01/22(日) 14:47:00.85パイプはそうではないという違いもあるよね
つまりcatが単に冗長で資源の無駄、というだけでなく
単純にcatではダメなケース(あるいは非常に非効率になるケース)が
厳然としてあるわけで、>>173の上司にはその点を訴えてみたらどうだろうか
stdout/stderrを何かに保存する目的でいずれにせよリダイレクトは使うだろうし
パイプのほうがリダイレクトより「初心者でも読める」というのは意味不明だ
なんかほんの少しでも合理的な理由があるのだろうか?
0192名無しさん@お腹いっぱい。
2012/01/22(日) 14:51:57.61バカな習慣を必死に言い訳すんなよ。羞恥プレー続行中か? w
複数ファイルを引数に取るのはどうすんだよ。
for f in $files ; cat $f |file -;done
こうか? スゲーぜ。 www
0193名無しさん@お腹いっぱい。
2012/01/22(日) 15:31:48.18fileは普通標準入力から読み込ませることはしないだろ?シェルスクリプトで使うこと前提だぞ、スレ的に
0194名無しさん@お腹いっぱい。
2012/01/22(日) 15:36:47.44何それ?
分割したバイナリを合体させるのに普通にcat使えるでしょ
catってfile結合コマンドだよ
0195名無しさん@お腹いっぱい。
2012/01/22(日) 16:05:46.12ありがとう。
機会ができたら、訴えてみる。
「初心者でも」っていうのは、ちょっとニュアンスが伝えにくいんだけど…気にしないで大丈夫です。
展開の順序とか考えず、コマンドを並べるならなんでもかんでもパイプを通せばいいじゃんって
新人とかへ教えるのが楽だから、そういう(ローカルな)文化になってるのかも。
0196名無しさん@お腹いっぱい。
2012/01/22(日) 16:13:11.56「ヒストリー使えないからダメ」とか言い出したのはやっぱり羞恥プレーか?
まあ、それは置いとくとして、「入力ファイルを区別できるからからcatして
パイプから流し込む」と言い出したバカをからかってるだけだよ。
入力ファイルは引数から渡した方が、
1 名前を渡せる。
2 シークも可能。
と、明らかに有利。
catはその名の通りファイルを結合する場合に使用する。
恥さらしな習慣の見苦しい言い訳まだ続ける?
0197名無しさん@お腹いっぱい。
2012/01/22(日) 16:59:14.69僕みたいなのもいるのですよ。 concatenate なんて…
0198名無しさん@お腹いっぱい。
2012/01/22(日) 17:13:08.18リダイレクトってシーク可能だったのか、知らなかった。
でもシークできるかできないかで挙動を変えるのはプログラム側だよね?
プログラムの実装でわざわざstdinがシークできるかどうかチェックするロジックって普通実装してある?
シーク前提のプログラムはそもそも標準入力から読み込もうとしないんじゃないかな。
0199名無しさん@お腹いっぱい。
2012/01/22(日) 17:37:41.83> プログラムの実装でわざわざstdinがシークできるかどうかチェックするロジックって普通実装してある?
お前のようなボンクラは知らないだろうが、必要ならばしている。
0200名無しさん@お腹いっぱい。
2012/01/22(日) 17:52:16.93fstat()で簡単に判断できるから、まともなプログラムならシーク可能かどうかは
「標準入力かどうか」ではなく、stat情報で判断する
ロジック的に1パス、シークエンシャルアクセスで行ける場合でも、
wavみたいなある程度でかいバイナリストリームを処理するソフトウエアでは
不要なチャンクをシークで飛ばせるかread()が必要かでは大違いなので
特にマルチメディア系ではシークが使える場合には使うのが普通
(そうしたプログラムがパイプで標準入力を利用可能なのも普通)
0201名無しさん@お腹いっぱい。
2012/01/22(日) 18:45:46.67ざっとbinutils、grep、awk、sedのソース漁ってみてが、無いな
0202名無しさん@お腹いっぱい。
2012/01/22(日) 18:50:17.20ボンクラがメクラ撃ちしたって当たらないって事の証明だな。
オレは一発でtailを見つけたが。w
lessもおそらくやってる。
■ このスレッドは過去ログ倉庫に格納されています