X



シェルスクリプト総合 その26 [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
垢版 |
2017/03/20(月) 12:07:26.41
シェルスクリプトの総合スレです。
□お約束
・特記なき場合は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.illumos.org/source/xref/illumos-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に逃げずにシェルスクリプトで処理するのが頭のいいやり方。
前スレ
シェルスクリプト総合 その25
http://echo.2ch.net/test/read.cgi/unix/1439563321/
0797名無しさん@お腹いっぱい。
垢版 |
2018/03/30(金) 03:18:23.09
OSっていうかGNU系かどうかだね
GNU系はだいたい\0に対応している
BSD系とかは対応してない。だからMacとかつらい

私的なスクリプトならMacのコマンドをGNU化するやつ
入れて済ませても良いんだが
0802名無しさん@お腹いっぱい。
垢版 |
2018/03/30(金) 15:47:33.25
コンパイルせずに実行できる(実質)唯一の共通規格言語だからじゃないの?
PythonとかはPOSIXの範囲外だからどこでも動くとは限らないし。
え? UNIX™なのにPOSIXと齟齬ありまくりの実装のAIXちゃん? 知らない子ですねぇ……。
0806名無しさん@お腹いっぱい。
垢版 |
2018/03/30(金) 17:23:17.72
俺が行ってる現場だと1年くらい前までは現役でPowerでAIXを使ってたよ。
今はRedHatにリプレースされちゃったけど……そんなに嫌いではなかった。

>>804
jotも無かったっけ?
0808名無しさん@お腹いっぱい。
垢版 |
2018/03/30(金) 20:26:28.33
>>801 >>802
それならシェル関数ではなく普通のシェルスクリプトでもいいだろう。
>>791 は単なるシェルスクリプトではなくシェル関数の利用にこだわってて謎。
0809名無しさん@お腹いっぱい。
垢版 |
2018/03/30(金) 20:31:30.33
シェル函数って
somefunc() {
echo "This is somefunc."
}
っていうやつでしょ?
>>791はそういう意味で使ったんじゃない可能性が出てきたな。
単に「パイプに渡せない」というような趣旨の要望を言いたかったのかもしれん。
0810名無しさん@お腹いっぱい。
垢版 |
2018/03/30(金) 20:47:44.46
>>809
たぶん find の -exec のとこに書けないって意味で書いてるだろうから、
シェルスクリプトじゃなくてシェル関数だと思う。
0811名無しさん@お腹いっぱい。
垢版 |
2018/03/30(金) 20:54:31.32
たとえパイプ経由でファイル名を渡せないって意味だったとしても、
find -exec でそれと同一機能が実現できるならそ別にいいじゃん。
>>791が find -exec の何を気に入らないのかやっぱり分からんな。
0813名無しさん@お腹いっぱい。
垢版 |
2018/03/30(金) 21:09:13.58
趣味なら理由になるかもなあ。

でも仕事じゃ理由にならん。
要件を満たしてるってのは仕事じゃ最低限度の基準だからな。

POSIXに適合するシェルスクリプトにしたいっていう要件が最初に出てるのに、
趣味に合わないから採用しない、仕方ないから実装を諦めるなんて奴がいたら、
仕事なら無能扱いだよ。
0815名無しさん@お腹いっぱい。
垢版 |
2018/03/30(金) 21:31:21.92
いや、あの謎のこだわりに合理的な理由があるのか、
それともホントに完全に趣味だけの話なのかが気になってたんだよ。
合理的理由ナシ、完全に個人の趣味ってことでFAなら、それでいいんだスマン。
0817名無しさん@お腹いっぱい。
垢版 |
2018/03/31(土) 01:12:03.45
aliasって面白いなー。これでなんか面白いことできそう

#!/bin/sh

alias foo="foo() { echo before; foo_; echo after; }; foo_"
foo() {
echo foo
}
unalias foo

foo
# ↓
# before
# foo
# after
0818817
垢版 |
2018/03/31(土) 01:41:51.42
やべぇ、このaliasの使い方、
めちゃくちゃ強力じゃないか?
文法の拡張が可能かもしれない
こんな所でネタにするレベルじゃないわ
0819817
垢版 |
2018/03/31(土) 02:06:02.61
黒魔術置いときますね

#!/bin/sh

def() {
alias begin="$1() { echo before; $1_ "\$@"; echo after; }; $1_() { $3=\$1"
alias end="}; unalias begin end"
}

def foo [ i ]
begin
echo foo $i
end

def bar [ j ]
begin
echo bar $j
end

foo 123
bar 456
0821名無しさん@お腹いっぱい。
垢版 |
2018/03/31(土) 02:48:01.26
>>820
bashとかだとデフォルトでは無効
expand_aliasesを使えば有効にできる

ただ>>817の挙動が全てのシェルで同じなのかは調べてない
aliasの挙動をちゃんと把握してはないけど
どうやら行単位で実行前に、単純な文字列置換が行われてる感じだね

だからevalでもできないスクリプトの自己書き換えみたいなことができちゃう

参考(ちゃんと読んではいないw)
http://magicant.txt-nifty.com/main/2017/10/yash-2-285-b4d8.html
0824名無しさん@お腹いっぱい。
垢版 |
2018/03/31(土) 22:32:30.06
みんな、変わった(?)の使ってるな。
Linux、BSD、Solarisなどのメジャーなもの以外で何がよく使われてるの?
0827名無しさん@お腹いっぱい。
垢版 |
2018/04/02(月) 07:41:52.65
$ man basename > man_basenam
でできるファイルを
emacsとテキストエディットで開いたものが次のものです。
https://imgur.com/a/8ggUs?
これはそういう仕様なのでしょうか?文字化けというか不思議な
コードになっています。できれば教えていただけないでしょうか
0831名無しさん@お腹いっぱい。
垢版 |
2018/04/02(月) 14:17:49.92
あと、emacs に限って言うと
M-x man
(ESC x man リターン)
と叩いて、man のエントリー名を入れれば、
きっちり整形した結果を表示してくれるから、
col -b を使う必要はあまりない。
0836834
垢版 |
2018/04/02(月) 21:28:17.87
これもしかしたらheadコマンドとnlコマンドの順番入れ替えると速度違う?
んなことないと思ってたけどビミョーに差があるかもしれん。
詳しい人検証してくれ……。
$ time for a in $(seq 10000); do seq 10000 > /dev/null; done
real 0m14.601s
user 0m0.452s
sys 0m3.736s
$ time for a in $(seq 10000); do yes '' | nl -b a | head -n 10000 | tr -d ' \t' | tr '\n' ' ' > /dev/null; done
real 1m2.693s
user 0m5.672s
sys 0m21.032s
$ time for a in $(seq 10000); do yes '' | head -n 10000 | nl -b a | tr -d ' \t' | tr '\n' ' ' > /dev/null; done
real 0m47.944s
user 0m1.472s
sys 0m17.820s
0838名無しさん@お腹いっぱい。
垢版 |
2018/04/02(月) 23:47:22.15
パイプで繋いでプロセス4つも5つも上げるくらいなら、
素直にawk 1プロセスですませた方が軽くないか?
0839836
垢版 |
2018/04/02(月) 23:56:24.81
>>838
俺awkできないんだわ。恥かしいことにw
そのうち勉強しようしようと思っていて今にいたる。

awkでやるとどんな感じになる?
0840836
垢版 |
2018/04/03(火) 00:14:31.67
ていうかseqの既定の出力を勘違いしてた
 $ yes '' | head -n 10 | nl -b a | tr -c -d '\n[:digit:]'
こんなもんかな?
$ time for a in $(seq 10000); do yes '' | head -n 10000 | nl -b a | tr -c -d '\n[:digit:]' > /dev/null ; done

real 0m42.358s
user 0m0.544s
sys 0m14.452s
0852名無しさん@お腹いっぱい。
垢版 |
2018/04/05(木) 02:42:14.79
sinyabin.shの中でradiru.shを実行しています。
sinyabin.shの中の変数をradiru.shに引き継ぎたいんですが、どう書けばいいんでしょうか?
0853852
垢版 |
2018/04/05(木) 03:31:27.11
radiru.shには、
pushbulettに録音開始の通知
ffmpegを使ってaacのダウンロード
l-smashを使ってaacをm4aに詰め替え
aacの削除
dropboxへm4aのアップロード
ローカルのm4aの削除
pushbulettに録音終了の通知をするコマンドを記入

radiru.shは
$ sinyabin.sh チャンネル 録音時間 ファイル名
で録音出来るようになっているので、

録画したい番組毎にsinyabin.sh等を作りその中に、
$ sinyabin.sh チャンネル 録音時間 ファイル名
を記入しています。

radiru.shの中のl-smashでaacをm4aにする際に番組名やアーティスト名などのタグ付けも一緒にやりたいので、sinyabin.sh側であらかじめl-smashで指定するタグのオプションを記入出来ればと思いました。
0854852
垢版 |
2018/04/05(木) 03:41:17.05
radiru.shはaacのダウンロードだけにして、
Pushbulettへの通知、l-smash、Dropboxなどはsinyabin.shの方に書いたほうがいいんでしょうか?
そうすれば、ちょっと録音したいと思ったときいちいち番組毎のスクリプトをつくりその中にIDタグなど細かく書かなくてもすむから楽かなと。
でもそれだと、番組毎のスクリプトに「Pushbulettへの通知、l-smash、Dropbox」といったコマンドを書かないといけないので無駄かなあとも思いました。
どういうフローがいいと思いますか?
0858名無しさん@お腹いっぱい。
垢版 |
2018/04/05(木) 13:53:42.01
プログラミング素人っぽいし、加減がわかってないだろうから、
情報が多すぎる方は不問にした方が。
足りないよりは多すぎる方がずっとマシ。
0860名無しさん@お腹いっぱい。
垢版 |
2018/04/12(木) 09:36:41.69
bashだと$LINENOでファイルの中での現在の行数が取得できるのですが、
dashやzshだと関数の中にいる時、関数のはじめからの行数になってしまいます。
どうにかして現在の行数を取得する方法はないでしょうか?
0862名無しさん@お腹いっぱい。
垢版 |
2018/04/13(金) 19:07:33.88
まぁやりようは如何様にでもあるんだろうが、
ニュアンス的に$LINENO並の手軽さで取得する手段はないかってことじゃね
俺は知らん
0865名無しさん@お腹いっぱい。
垢版 |
2018/04/13(金) 23:40:07.60
実装オプションにつけてあるIDコードの一つみたいだな。
コードの一覧は
ttp://pubs.opengroup.org/onlinepubs/9699919799/help/codes.html
にある。

オプション機能なので、実装されてるとは限らない。
0866名無しさん@お腹いっぱい。
垢版 |
2018/04/14(土) 00:40:09.23
LINENOが仕様どおりに実装されてないのは
この際見なかったことにして、現在使われてる
POSIX準拠シェルで完全に実装されてないものなんて有るの?

そもそも現在使われてるPOSIX準拠シェルってどんなのがあるんだろう
bash、ash、dash、zsh、ksh、mksh、yash、posh
他に知ってる?
0868名無しさん@お腹いっぱい。
垢版 |
2018/04/14(土) 19:01:06.26
デバッグログ以外になにかあんの?
だからこそデバッグログとして使えない
$LINENOを何のために作ったのか理解できない
0872名無しさん@お腹いっぱい。
垢版 |
2018/04/18(水) 10:39:06.43
自己解凍するファイルって便利だな
シェルスクリプトで解凍とインストール手順を記述して
それをバイナリと結合するだけでmsiみたいなことができる
0873名無しさん@お腹いっぱい。
垢版 |
2018/04/18(水) 15:04:27.31
>>872
それはちなみに sh アーカイブ形式って呼び名がついてる。
sharっていう自己解凍シェルスクリプト作成専用コマンドも昔はあった。

なお、ウイルスやマルウェアの温床だということで廃れた模様。
0874名無しさん@お腹いっぱい。
垢版 |
2018/04/18(水) 15:22:26.44
sharはそれでインストールまでするというより、tar.gz などのバイナリファイルを
テキストにしてメールやニュースで送るために使うことが多かった
0876872
垢版 |
2018/04/18(水) 21:50:42.61
あーわりと昔からある手法なのね……
VMware Horizon Clientのインストールイメージがその形で,俺は正直そういうシェルスクリプトとバイナリが結合されてるファイルを始めて触ったんで
画期的なアイデアに思えたんだわ……
0877名無しさん@お腹いっぱい。
垢版 |
2018/04/18(水) 23:47:33.56
echo "1 + 2" | bc > /tmp/a
とすると/tmp/aには2バイト、16進数で
33 0a のデータが入っています。

a=$(echo "1 + 2" | bc)
printf "$a" > /tmp/a
しかしこうすると$aには1バイトしか入ってないようです。

また [ "$(printf '1')" = "$(printf "1\n\n\n\n\n")" ]
これは一致した文字とみなされるようです

こういった挙動はどこを見れば理解できるでしょうか?
0878名無しさん@お腹いっぱい。
垢版 |
2018/04/18(水) 23:55:18.86
a="$(printf '1\n\n\n')"
とやってもaには1しか入っていない

a="$(printf '1\n\n\n2')"
しかしこうすると5バイト入ってる

その状態から a=${a%?} を末尾の2を削除すると
a には4バイト、1\n\n\n が入っている

うーん?
0879名無しさん@お腹いっぱい。
垢版 |
2018/04/19(木) 00:06:08.07
>>877
コマンド置換 $(...) の仕様

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_03
> removing sequences of one or more <newline> characters at the end of
> the substitution. Embedded <newline> characters before the end of
> the output shall not be removed; however, they may be treated as
> field delimiters and eliminated during field splitting, depending on
> the value of IFS and quoting that is in effect. If the output
> contains any null bytes, the behavior is unspecified.

bashのマニュアルにも同様の記述がある

http://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html#lbBC
> bash は command を実行し、 command の標準出力でコマンド置換の部分を
> 置き換えます。この際、末尾の改行文字は削除されます。 文字列の途中に
> ある改行文字は削除されませんが、 単語分割の際に削除されることがあり
> ます。
0881名無しさん@お腹いっぱい。
垢版 |
2018/04/19(木) 00:19:37.42
コマンド置換の仕様かぁ

普通のやり方ではコマンドの出力結果を変数に入れるときは
末尾の改行は絶対消えるってことかなー
read使えばって思ったけど、あっちは改行区切りだしなー

ちなみに $aに1\n\n\nを無理やり入れて、
$bに1を入れて [ "$a" = "$b" ] で比較したら不一致になったよ
0884名無しさん@お腹いっぱい。
垢版 |
2018/04/24(火) 02:26:08.83
単純なルールのほうが整合性は取りやすいんでは? 寧ろ複雑な規則だと実装に矛盾が生じたりしそう。
0885名無しさん@お腹いっぱい。
垢版 |
2018/04/27(金) 23:17:19.66
ちょっと質問
偶数日と奇数日で処理を分けたいんだけど、上手くできない
どうしたら良いのかアドバイスください

#!/bin/sh
DATE=`date '+%d'` # 日 を取得
buf=$(( $DATE % 2 )) # 計算

if [ ! $buf ]; then # 偶数
 hoge
else # 奇数
 fuga
fi
0887名無しさん@お腹いっぱい。
垢版 |
2018/04/28(土) 00:55:01.80
>>885
#! /bin/sh -

DATE="$(date "+%d")"

if [ $((DATE % 2)) -eq 0 ]; then
echo "今日は偶数Day"
else
echo "今日は奇数Day"
fi

ある種の言語(Cとかだっけ?)はif文に0を放り込めるけど、
コマンドを逐次実行するだけのシェルスクリプトでは無理。
面倒だけど数値判定をしなきゃいけない。
あと、>>886氏の言う通り演算置換内の変数に弗記号は不要。
あと、コマンド置換は容易く入れ子にできて対も分かりよい$()を使おう。
POSIX sh 2003でもサポートされているので安心して。
0888名無しさん@お腹いっぱい。
垢版 |
2018/04/28(土) 01:37:16.44
BSDで標準コマンドだけで現在時刻(もしくは起動してからの)ミリ秒ってとれないのな
/proc/uptimeもBSDないみたいだしどうにかして取れないかなー

ファイルに書き込んでタイムスタンプで
取れないかなーとかもやってみたりもしたw
ファイルシステムによっては書き込まれるみたいだが
これも標準コマンドだけでどうやればー

できればなにも入ってない素のコマンドだけでやりたいんだよね
Perlでもやれるけど、dateコマンドに比べたら
起動時間が10倍も違うんだよな。

あ、ベンチマークというかコマンドの実行速度を細かく知りたいために使いたい。
timeコマンドは標準出力(エラーだっけ?)を乱すので使いたくない
0890名無しさん@お腹いっぱい。
垢版 |
2018/04/28(土) 19:41:21.09
>886-887
ありがとうできたよ。bufが空白になって常にelseに倒れてたから助かりました。
$の位置が良くわからなくて困っていたんだ

Cならいくらでも書けるんだけど、慣れない言語はちょとね・・・
0891名無しさん@お腹いっぱい。
垢版 |
2018/04/28(土) 20:34:44.86
>>888
timeコマンドの出力は標準エラーだよ。
標準出力の方は乱さない。

標準エラーが乱れる方も
(time sh -c '測りたいコマンド 2>&3' 2>/tmp/time.out ) 3>&2
みたいにすれば回避できるから、素直に time コマンド使う方がいい。
0892名無しさん@お腹いっぱい。
垢版 |
2018/04/28(土) 23:27:39.64
>>891
もう一つ問題があってなぁ。
dashじゃtimeコマンドビルトインじゃないんだよ
ビルトインじゃないからシェル関数で使えないんだよね
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況