シェルスクリプト総合 その33
■ このスレッドは過去ログ倉庫に格納されています
シェルスクリプトに関する総合スレッドです。 全般 ・荒しは無視しましょう。 ・丁寧な姿勢を心掛けましょう。 ・ネチケット(死語)を意識しましょう。 ・「○○(他の言語)でいいやん」は禁止。他のスレに行ってください。 シェルスクリプト総合 その32 https://mevius.5ch.net/test/read.cgi/tech/1571929725/ え,関数って一行で定義するときは foo() echo hello; みたいに波括弧で括る必要ないの? 知らんかった。 >>175 リンク先見ろ、Grouping Commands って書いてあるだろ compound-command は () や {} でグループ化してもいいし、しなくてもいい 単一のコマンドも compound-command というか、単一のコマンドが compound-command であり 複数のコマンドをまとめる時に Grouping Commands を使う >>176 本来はね。でもbashで対応してないから事実上諦めるしかない。 >>176 あとグループ化するのに使うのは {} または () なので foo() { echo hello; } の代わりに foo() (echo hello) と書いても良い こっちはbashやyashも対応している。 ただし当然のことながらサブシェルで実行される。 fname ( ) compound-command [io-redirect ...] の最後からわかるように foo() { echo hello; } >/dev/null や foo() (echo hello) >/dev/null とも書ける もちろん複数行でこのように書いてもいい 関数が出すエラーを全て捨てる場合とかに使える foo() { echo hello } 2>/dev/null >>177 > 単一のコマンドも compound-command > というか、単一のコマンドが compound-command であり それ初耳だわ どこに書いてある? >>181 なんのために Grouping Commands と別に説明してある思ってる? Grouping Commands を作るための {} または () が必須じゃないから、 「compound-commands の定義は {} または () で始まる」と*書かれてない*んだよ 2.9.4 Compound Commands The shell has several programming constructs that are "compound commands", which provide control flow for commands. Each of these compound commands has a reserved word or control operator at the beginning, and a corresponding terminator reserved word or operator at the end でその後Compound Commandsとして上げられてるが以下の6つ - Grouping Commands - The for Loop - Case Conditional Construct - The if Conditional Construct - The while Loop - The until Loop echo helloは開始・終了を示す予約語もなければ、上の6つのどれにも当てはまらないからCompound Commandではない foo() if true; then echo "foobar"; fi ↑こういうのはOK ↓shellcheckの解説 POSIX allows the body of a function to be any compound command, e.g. foo() for i; do :; done. Since this usage is rare, ShellCheck intentionally requires the body to be { ..; } (or ( ..; )): https://github.com/koalaman/shellcheck/wiki/SC1064 >>183 Compound Commands はその6つって言いたいの? なら以下の関数定義はPOSIX 準拠ってことだね foo() for i in a b c; do echo $i; done foo() case a in a) echo a; esac foo() if [ a ]; then echo a; fi foo() while [ $# -gt 0 ]; do echo $1; shift; done <<. dash foo() echo hello foo . hello たしかにDashだと問題なく定義できるな……。 こんなこと始めて知ったわ。実地で使うかどうかは置いといてw >>169 type { }やると分かるけど{}はシェルの予約語 {}に意味があるから{ この空白も閉じる前の;}もいる for i inをforiinにできないようなもんで ()はtypeで何も出てこないけどね set -eの挙動について教えて下さい! これを実行したら何も表示されずに終了されました set -e foo() { false echo foo } foo echo $? その理由はわかります 質問はfooの中身を一切変えずにset -eの状態で fooを画面に表示させずに $? (= 1) を 取得する方法はあるのでしょうか? { と [ は記号でなく「コマンド」 $ ls -l を $ ls-l とスペースを入れないと動かなくなる これと一緒 >>190 ! ret=foo echo $? or if ret=$(foo); then echo "truthy" "$ret" "$?" else echo "falsy" "$ret" "$?" fi >>192 > ! ret=foo なんですか、これ!?って思ったらfoo関数呼び出してないじゃないですかぁ > if ret=$(foo); then なるほど、これで取得できるんですねって思って やったんですけど truthy foo 0 ってでました >>190 パイプライン (1 つの 単純なコマンド からなるものでもよい)、 括弧で囲まれた サブシェル のコマンド、 ブレース (前述の シェルの文法 を参照) で囲まれたコマンドのリストの一部として 実行されたコマンドの 1 つ が 0 でないステータスで終了した場合、即座に終了します だから。falseの時点でどうであれメインシェルプロセスがそこで終了、echo fooなんて実行しない、もちろん呼び出し元にも戻らない >>192 は上記に続く文に沿ってのじゃないかなあ。だが、if false; then ... とかの話で、違うだろうな文的にも。わざとなのかわからんけどw そういう動作を望んで set -e してるのにそういう動作すんなって無理じゃね bash 限定なら、 export -f foo bash -c 'foo' && echo $? || echo $? で、一応動くようではあるな(ちゃんとfooでのステータス値も返る) >>195 bash -c 'set -e;foo' && echo $? || echo $? だった。set -e は別に継承されるわけないと後で気づいた で、>>192 のネタ確認してみたらできそうなのね。$()なんて出力結果求めるのにしか使ったことないのでこれでいいのか??と頭ウニだけど if $(set -e && foo); then echo $?; else echo $?; fi なんかbash限定でもなく動いてるな(w) あぁ、$() は正常時はやっぱりダメか。そりゃそうだな(スッキリしたw) ret=$(foo) のような、なんか工夫すればできそうな気もしないでもないが。そういうことなのね、失礼>>192 その方針なら export -f foo; ret=$(bash -c 'foo; echo $?'); echo $ret; で良いんじゃね? 出力結果をスクリプトで扱うために欲しいわけじゃないから $() だと関数も外部コマンドのように別(のメイン)プロセスとして呼べる=bash固有のでなくて使えそうだなあという、ニコイチではなくどっちかの話 $ $(echo hoge) hoge: command not found まあ、当然そうだわな $ $(exit 12) $ echo $? 12 へー、コマンドねえぞとお怒りにはならんのか。空行とみなして無かったこと(?)になるのか echo ' 'とかスペースタブだけ(?)なら許してくれる、: と違いステータスも変わらない てことで、標準出力に何も出さなければいいのねで、 exec 9>&1 $(set -e; foo >&9) && echo $? || echo $? でbash以外でも動くことは動く ($() 内ってCommandsでもいいのね) $()内での set -e はない方がスッキリだが必要ないシェルもあるもあるが必要とするシェルがある 例えば、Ruby のバージョンマネージャー・rbenv の、rbenv-installer の冒頭部分は、 #!/bin/bash # コマンドの終了コードが、0以外なら強制終了する set -e homebrew= # -p : タイプが「file(実行ファイル)」の時のみ実行ファイルの絶対パスを出力する # (それ以外のタイプの場合は何も出力しない) type -p brew >/dev/null && homebrew=1 コマンドってファイルに書くのと実行形式を~/binに置くのとどっちがいいの 関数とエイリアスの違いは分かったけど使い分けできてないな /dev/urandomっていうデバイスファイルが, ほんとにただのファイルとか実は同じ値ばっかり出力するデバイスファイルとか じゃないってことを保証する方法ってある? >>203 いろんなところで使いたいコマンドは ~/bin に置いておいて パスを通しておく。限定的な使い方をするコマンドはそのディレクトリに 置いておくのかな。私はそうしている。 >>204 ないよ。 作ろうと思えば/dev/urandomを独自実装のデバイスファイルに置き換えられるんだから。 それっぽい値を返すデバイスファイルを作ろうと思えば作れる 例えばWSL1はWindowsでLinuxカーネルをエミュレートしてるんだから /dev/urandom とかMSの独自実装のデバイスでしょ? >>203 コマンドをファイルに書くって関数のこと? CLIから呼び出す汎用的なものは~/binで スクリプト内部で使うだけなら関数にするだけじゃないの? そしてエイリアスはインタラクティブシェルで使うもの bashがデフォルトでスクリプトでは無効になってるのはそういう事 >スクリプト内部で使うだけなら関数にするだけ と思い込んでたら、>>56 みたいになるぞw >bashがデフォルトでスクリプトでは無効になってるのはそういう事 まあ、4からか?そういう方がいいだろうと思い変えたのだろうが、--posixでは有効なんだけどな >>56 は、rbenvはインタラクティブシェルで使うために alias使ってるんでしょ? > まあ、4からか? ずっと前からやろ? >>209 >alias使ってるんでしょ? ああ...これもか... 色々想像するのは勝手だが、なんか色々勝手な想像ばかりで全く調べてないなって感じだぞ >>209 ,211 ああ、すまん 実行できないのは最初からだし、存在さえもしないのは3以降からだな(2では存在はするが実行時エラー) >まあ、4からか?そういう方がいいだろうと思い変えたのだろうが の部分は間違い勘違い、すまん >>213 調べるとか何のこと? スクリプト内部でだけ使うなら関数って言ってるだけなんだけど? anyenv は多言語向きで、rbenv, nodenv, pyenv, phpenv などを同じ使い方で、統一的に扱える。 ~/.bashrc に、下の2行を追加するだけで、各言語ごとに追加しないでも良い export PATH="$HOME/.anyenv/bin:$PATH" eval "$(anyenv init -)" 結局、この追加した、eval で、rbenv という関数を読み込んでいたという落ちw >>165 に書いてます シェル関数は、その関数が定義されたファイルを読み込んでいれば使えるけど、 読み込んでいなければ使えない >>215 想像でそれも自分の言ったことに都合が良いだけで言うなってことだよ すぐ下のレスに状態を本人が書いてるだろに rbenvはaliasをインタラクティブシェルで使ってない だからといって、 「aliasはインタラクティブシェルで使うもの」を 否定してることにはならんのだが・ 何言ってるの? >>スクリプト内部で使うだけなら関数にするだけ >と思い込んでたら、>>56 みたいになるぞw から、想像だけで「alias使ってるんでしょ?」て間違ったこと「いきなり」言い始めたんんだけど。それが関数なんてすぐ下に書いてあるのに、見も/調べもせずに「いきなり」 「スクリプト内部で使う[だけ]なら[関数]」だから、見も/調べもせずに「alias使ってるんでしょ?」なんて間違いを平気で言ったんでしょ? aliasはインタラクティブシェルで使うものは別件で、そこは関数のことだろに aliasはインタラクティブシェルで使うものは特に否定はしてないが、POSIXでそう決めてるわけではない。>>210 を自分でちゃんと読めば>>210 はなんの補強にもなってないのに誤った抽出ってこと 「スクリプト内部で使うだけなら関数にするだけ」は 否定しないんだね 読めなさすぎだろう。なんでそうなる?? スクリプト内部で使う[だけ]じゃない[関数]がって例の話なのに ダメだな読めなさすぎ、今までのでも 枯れた技術のスレで質問禁止にしたら超絶過疎っちゃうよ 質問禁止という意味じゃない。質問もありだし質問のをネタにしたのもあり 質問箱スレならQ/A以外は雑音にしかならんという意味 cronの書式を読み取りたいんですがなぜかファイル名が読み取られてしまいます。なぜでしょうか? どうやったらそんな挙動になるんだ? ちょっとどんなコマンド打ったか書いてみて。 >>228 クォートしてないからでしょ $ ls crontab $ echo * * * * * user-name command to be executed crontab crontab crontab crontab crontab user-name command to be executed $ echo "* * * * * user-name command to be executed" * * * * * user-name command to be executed >>229 setを使ってスペース区切りで分割したらファイル名になりました >>230 そこから各フィールドごとに分割するのはどうしたらいいでしょうか? cat /etc/crontab | grep -v '^[ \t]*#' | while read m h D M W u c; do [ "$c" != '' ] && echo "$M/$D $W $h:$m ($u) $c"; done でいいのかな?? しかし、>>228 から * のGLOB展開とわかるなんてすげえなw>>230 は 他スレで -z とか見て思い出したんだけどさ [ -z "$str" ] とか [ -n "$str" ] って必要なの? [ "$str" ] とか [ ! "$str" ] でいいと思うんだけど? [ "$op" "$str" ] みたいに演算子を変数に入れられるから 機能そのものが不要だとはは思わないけど 通常は [ "$str" ] や [ ! "$str" ] で良くない? 他の言語だとこっちだからわかりやすいし 他の言語だったらそういうのはBooleanでしか使わないという文化な人々も居る [ -z "$str" ] や [ -n "$str" ] よりも [ "$str" = "" ] とか [ "$str" != "" ] の方が見る機会が多かったな >>236 先頭にマイナス記号が入らないことが保証されるのならいいのでは? >>238 関係ないでしょ? その場合こう展開される [ "-z" ] または [ "-n" ] これはどちらも文字列があるから0 [ ] で囲まれた中身が1個の場合は決してオペレータとして扱わないのだから どんな文字が来たとしても問題ない。空文字以外は0となる ついでにいうと [ ] の中身が0個の場合は常に非0 そもそも [ ] (test)のドキュメントに STRING は -n STRING と等価と書かれている 仕様通り >>240 -a と -o に関しては、shellcheckさんが禁止しております [ 略 -a 略 ] は使いません。必要なら [ 略 ] && [ 略 ] こうします >>241 そういう独自ルールを適用するならそれで良いんじゃねえか? ただ独自ルールだからそれとセットで説明する必要がある。 >>242 ん?でもさ -a とか -o 使っても問題ないんじゃね? [ str -a ] みたいなのってありえないんだからさ[ -a -a ] もないでしょ? [ -a -a -a ] だと 最初と最後が文字だって一意に識別できるよね? 訂正する > 他の条件とand/orされる場合は? 他の条件とand/orされる場合 かつ 混乱するようなパターンってありえるの? >>243 シェルというかtestコマンドってそんなに賢く自動判別してくれるの? これからそういうシェルまたはtestコマンド作るって話? だったら作ればいいんじゃね?そうすればそれはそういうものですって言えるしそれでokだ。 なんでシェルをディスってるの? これからも何も「testは賢く判断するから問題ないよね」って聞いてるだけなのに >>244 こういえば良いのか? POSIXで決まっている仕様どおりの正しい動きです。 これから作る必要など全くありません。 >>236 と同一人物に見えて俺流儀の押し付けしたいのか何をしたいのかだろな 質問者 (POSIX準拠の仕様)これ問題ある? 回答者 問題あるに決まってるだろ。あれとかこれとかどうなんだ? 質問者 それらは問題ないよね? 回答者 お前の流儀を押し付けるな! なんだこのながれ /\___/\ / / ヽ ::: \ | (●), 、(●)、 | / ̄ ̄ ̄ ̄ ̄ ̄ ̄ | ,,ノ(、_, )ヽ、,, | < まーたはじまった | ,;‐=‐ヽ .:::::| \_______ \ `ニニ´ .:::/ /`ー‐--‐‐―´´\ まともなレスじゃなくて、個人たたきに変わったからな POSIXの仕様にたいして俺流儀とかアホかと 俺流儀に見えたってことはそういうことでは 虚栄心だけじゃ何も学べないよねぇ 最近Oil ShellのPOSIX準拠度が高まってきて嬉しい(これはネタじゃない) ち、やっぱり set -uしたときにecho ${A+x} ってしたら fatal: Undefined variableで落ちるじゃねーか 変数が定義されているかのチェックすら出来ねぇ >>266 立て逃げしていいならするけどさ、やり取りが面倒なんだよ この程度ででるぐらいなら他にも問題たくさんありそうだしstar多いんだろ?誰かが頑張ってくれ それかすでにあるんじゃねーの?OilShellがどこまで本気なのか知らんが、 まがりなりにもPOSIX準拠を名乗りたいのなら絶対には対応していないといけない 基本機能だからな。(変数定義確認方法のFAQレベルだぞこれは) 俺にとっては数あるシェルの一つでしかないし別件で忙しい POSIX互換を謳う俺々シェルの利点って何なの わざわざ作るってことは今のPOSIXは不備あるのか >>268 今のPOSIXに不満があったらPOSIX準拠シェルなんて面倒なもの態々作らんと思うが 作るだろ?不満があったから新しいものを作る ただし移行パスがなければ移行しないのでその方法を提供する よくある話だ >>270 たぶん「準拠(互換)」の部分について言及してるんだと思うよ 学術の巨大掲示板群 - アルファ・ラボ ttp://x0000.net 数学 物理学 化学 生物学 天文学 地理地学 IT 電子 工学 言語学 国語 方言 など PS 連続と離散を統一した! ttp://x0000.net/topic.aspx?id=3709-0 学術の巨大掲示板群 - アルファ・ラボ ttp://x0000.net 数学 物理学 化学 生物学 天文学 地理地学 IT 電子 工学 言語学 国語 方言 など PS 連続と離散を統一した! ttp://x0000.net/topic.aspx?id=3709-0 POSIX 抽出レス数:28 スレタイに【POSIX】いれとけよ ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる