シェルスクリプト総合 その27
■ このスレッドは過去ログ倉庫に格納されています
シェルスクリプトの総合スレです。 □お約束 ・特記なき場合はBourne Shell(/bin/sh)もしくはPOSIX準拠の互換シェルがデフォルトです。 bash/zsh/ksh/ash/dash/yash/poshなどの専用機能に依存する場合は明示しましょう。 Linuxユーザは/bin/shの正体がbashまたはdashなので特に注意。 FreeBSDユーザは/bin/shの正体がashなので注意。 ・POSIXについてのリンクは https://en.wikipedia.org/wiki/POSIX にまとめられています 最新の仕様はこちらへ http://pubs.opengroup.org/onlinepubs/9699919799/ (左上の「Shell & Utilities」 から参照することができます。) ・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に逃げずにシェルスクリプトで処理するのが頭のいいやり方。 質問に対して問題が間違ってるといちゃもんをつけるのもやめましょう 前スレ シェルスクリプト総合 その26 https://mevius.5ch.net/test/read.cgi/unix/1489979246/ >>668 ? もしかして-type fが見えてないだけ? パスの中に空白が入ってる or PATHの中身が多すぎたらおそらくアウト ( IFS=:; find $PATH -type f -a -perm -+x ) | sed 's|.*/||g' | sort | uniq -c ( IFS=:; for i in $PATH; do find "$i" -type f -a -perm -+x; done ) | sed 's|.*/||g' | sort | uniq -c できればsedでやりたいことなんですが aaa << bbb >> もしくは aaa <<bbb>> というようなファイルがあったとしてaaaの次行から「>>」を含む行までを読み出したいです。 (aaaが存在する行はすでに具体的な数値で判明しています; ここでは42行目とします) 特に二番目の場合には sed -n -e '43,/>>/p'とやると43行目に「>>」があるのに見つけてくれません。 なにか手助けをおねがいします。 >>671 sed -e '42,/>>/!d' -e 42d あれんじ sed -e '43,$!d;/>>/q' 言っても無駄なんだろうが、そんなファイルを処理しようってのが間違ってると思う >>676 処理したい時はどうすればいいですかね。 Windowsだと%TEMP%で一時ファイルの格納場所が指定できますがUnixではそういう環境変数はないのですか? $TEMPとか >>669 basenameって拡張子消えるよね? >>679 誰に対して使用して欲しいのか分からないな >>679 TMPDIR かな /tmp が古からあるからな。TMPDIRが設定されていたら(OSとして初期設定されているか、なんらかの形でTMPDIR設定されてたら)TMPDIR。設定されてなかったら普通に /tmp かな >>679 ,683 >TMPDIRが設定されていたら〜 って、TMPDIRを意識していればね。当然のように、んなの知らん、/tmp 一択ってのも普通にある >>681 一応、TMPDIRはPOSIX標準環境変数らしい。 tmpfile(3)やmkstem(3)なんぞはPOSIXとしてはTMPDIRを参照しろとはなってないらしい が、実装するならTMPDIR参照するだろうし、してる。ちゃんとtmpfile(3)やmkstem(3)やmktemp(1)などを使っていれば、誰でもなんだろうけどね >>685 それってPOSIX shellの話なの? 関数のなかってalias使えないっぽいね somefnc() { alias AAA='pwd' AAA } # → AAA: command not found 6.6 Aliases ... Aliases are expanded when a function definition is read, not when the function is executed, because a function definition is itself a compound command. As a consequence, aliases defined in a function are not available until after that function is executed. somefnc () { alias AAA='pwd'; } somefnc AAA otherfnc () { AAA; } otherfnc aaa="cat /etc/*release | grep -E '^NAME='" echo ${aaa} 上を実行すると、 $ ./hoge.sh cat /etc/os-release | grep -E '^NAME=' こうなってしまいます。 cat 〜の結果をaaaに入れる方法教えて欲しいです。 >>690 関数の中でaliasが使えないと言うよりか、 関数の定義が実行された時点でのalias情報が反映される。 つまりシェルスクリプトを上から実行していって、 somefunc()関数定義文が見つかると、 この関数 "全体" に対して、alias展開処理が行われてから関数が定義される だからsomefunc()関数定義文よりも前にaliasが設定されていれば そのとおりに展開されるが、関数の中はすでにalias展開済みなので もう処理されない ちなみにこれだとうまくいく somefnc() { alias AAA='pwd' eval AAA } evalは実行する段階でalias展開されるようだ evalで実行する文は、実行段階ならないと わからないのだから当然ではあるが >>695 すげぇ!ありがとう ちなみに今さっきの地震に伴う停電のせいでパソコンがおしゃかになったっぽいので 試せないw うちの研究室もすごいことになった。 ところで前々から関数のなかで alias が展開されないのを歯痒くおもっていたので eval 使えばいいというのは非常に有益な Tips だわ。 あまりにもPOSIX、POSIXしつこいから、POSIXでNGにしたったわ >>699 makefile とか crontab でもエイリアス無視だけど evalならいけるのかな 試してみよう 関数の中、もしくはmakefileやcrontabで aliasを使いたい状況っていうのがよくわからないが どんなときに使うの? aliasではなく変数とかじゃ駄目なの? 自分は引数を取らず固定されたフィルタはaliasで定義することにしている 例えばeraelコマンド(ERAce Empty Line)。 alias erael='sed -e "/^$/d"' ただ大抵はシェルスクリプトの先頭に記述するのであなたの言う通り関数の中で宣言する意図は分からん。 >>708 使い方としてはわかったけど、 ぶっちゃけそれだって関数作ればいいだけなんだよなぁ erase() { sed -e "/^$/d" "$@"; } >>710 いやそうなんだけど 「引数を取らず固定されたフィルタ」 ↑これを実現するのに関数は大仰な気がしてきてな。 関数とエイリアスの使い分けに意味はあるの? 使用メモリ?性能? >>712 いやまったく大差ない。 ただただaliasというだけ 分かってると思うが俺は別に「使え!」なんて言ってないから そんな気にする必要ないぜ。 個人的な問題だから。 みんな知ってるかい? 関数の中で関数を定義できるってことを foo() { bar() { echo bar } } foo bar foo() { bar() { echo bar } } foo bar 5chに貼られたソースコードをコピペするってwセキュリティ意識ゼロかよw 絶対こんなの相手に発注したくねぇww >>717 たかが数行のソースが危険かどうかもわからん奴には発注したくないな somefunc() { echo "${1:='need a arg'}" } のような関数を作ったのですが引数なしで起動すると -bash: $1: この方法で割当はできません と怒られるのですがどうすればいいですかね。 somefunc() { arg="$1" echo "${arg:='need a arg'}" } >>721 ありがとうございます! できました! すいませんが、もしよければなぜ直接引数に:=変数置換を適用できないのか教えていただけないでしょうか。 例えば${1:-aaa}などはごく普通にできるので、不思議です。 bash: $1: この方法で割当はできません bash: $1: cannot assign in this way 代入文を使って位置パラメータへの代入を行うことはできません。 Positional parameters may not be assigned to with assignment statements. すべての言語で引数に対する代入は禁止されればいいのに Cだとargvは一度どこかに書き出さないと置換とか操作できないよね。 >>728 別に直接書き換えもできる。constを「自分で」付ければできないようにもできるけど Cで書き換えるのは危険すぎるだけだな。配列/文字列等のメモリ境界保護なんてないから。OSによってはargvがメモリ保護域にあるのもあるだろけど >>728 argv の指す先は変更できないけど argv 自体は変更し放題 >>730 argvの指す先(char **argv/*argv[]の中身/値でいいの?)も変更できるよ argv = myArgv; argv[1] = myArg; argv[1][0] = myChar; どれもできる ああそうか。728だけど,すごいまぬけな発言をしてたわ。 Cでのargvはあくまで約束事としての変数名だからなんの保護・制約も掛けられてないのか。 一方シェルスクリプトでは引数変数を明確に他と区別できるようになってる。 ただし半保護状態。 script(1)コマンドかそれと似たCLI記録ツールで、 ~/.profile(←ここに~/.bashrcなどを読みこむコマンドが書いてある)を読み込ませたいのですがどうすればいいですかね。 >>733 #!/bin/sh exec /bin/bash --init-file "$HOME"/.profile "$@" こういうスクリプトを書く ファイル名を mysh でホームに保存したとして、次のようにして script に使わせる env SHELL="$HOME"/mysh script >>733 surce ~/.profile ではだめなの? ✕ surce △ source ◯ . bashの場合、インタラクティブでログインシェルでなければ.bashrcを読むはずだけど、それじゃ足らんの? 733です。すいません。もうひとつ訊きたいことがあるのですが script(1)実行中はCOLUMNS=80,LINES=25に固定したいです。 しかしそのmyshに export COLUMNS=80 などと記述しても反映されません。 ~/.profileなどでは特にCOLUMNSの値を設定している訳ではないです。 これどうすればいいですかね stty cols 80 rows 25 なんかLINESもってとこから、ターミナルのウィンドウサイズなんぞもってぽいけど、それは個々のターミナルアプリ次第&一方通行っぽい(COLUMNSの値を設定している訳ではないのはそゆこと)けど シェルスクリプトってeval使えばメタプログラミングっぽいことできるよね。 例えば引数をfor文で増加さしてeval arg$i=\$$iみたいな。 >>742 evalはインタープリタそのものだからね evalは一番最初に現れたプリミティブなメタプログラミング機能だからまあ当然だな。 ちな最初にeval を発明した言語はLisp な。 evalは強力すぎて危険だからどの言語でも濫用はevil扱いだと思う。 REPLみたいにevalがぴったりした応用もあるから禁止はできんし、 シェルスクリプトは比較的ミニマムな言語だからevalしか解がないケースも多いけど。 「ミニマルな言語」って他には例えばなに? それLLとはまた違うの? いや煽ってるんではなくて単純に訊ねたい。 コマンド置換の入れ子の限界を試そうと思って $ i=1; while true; do echo $i; eval $( (yes '$(echo' | head -n $i | tr -d '\n'); (yes ')' | head -n $i | tr -d '\n') ); : $((i++)); done ↑こんなコードを実行してみた。 100あたりから面白いくらいに遅くなっていく しかし500くらいまで試したけど表示は続き、限界を探る目的は達成できなかった。 eval関連なんですがaliasの出力結果をevalする方法を教えてください。 具体的にはroot権限でlsがしたいのですが、その時通常のlsと同じオプションを付けて実行したいのです。 ですので(通常の状態での)alias lsの結果を変数かなにかに格納してそれを実行しようと思ったのですが良い方法が思い付きません。 そのコマンド自体もaliasにしたい(具体的にはls@rootコマンドとしてalias ls@root=の形で定義したい)です。 どうかよろしくお願いします。 すいません。一番上の行は無視してください。 evalでできるかなと考えてたプロセスが漏れてしまっただけです。 多分このアプローチは間違っているので無視してください。 >>750 偽物臭強いけどなw ただ身長が小さいだけじゃないかっつー 本物双子のやつは結構好き >>751 aliasでなくてsudo使って関数定義するのがいいと思うけどだめなの? >>748 データ型が少ないって意味でTclとかかな。 でもTclには文字列型の他に連想配列があるのよね。 POSIX shellの範囲内だと引数配列を除けばホントに文字列しかないので。 こんにちは ド素人です。 VPSの立ち上げ時にスタートアップシェルスクリプトを使って効率化したいです。 とあるwgetを叩くと、user名とパスワード、パスワードの再入力を求められるのですが、 このuser名、パスワードをシェルスクリプトで入力させるにはどうしたらよいでしょうか。 wgetでgithub上にある既存のシェルスクリプトを叩くと ユーザー名とパスワードを聞かれるのですが、 その入力を自動化したいという意味です。 github上のシェルスクリプトは変更できません・・・ wgetでシェルスクリプト叩くてどういう意味? 出力をシェルに流し込むって事? なんかパスワード 自動入力 あたりでggったらすぐ出てきそうやな >>761 相手側の要求に従ったuser名パスワードの提供方法をwgetでするとよいでしょう どのVPS?どういう相手側のサービス?その使ったというはGitHubのどれ? https://gist.github.com/kevinold/216077/4d725773b46a2ac32c0f5a689339d3da004d7f5d これでいいのか?適当にぐぐったらVPSだしwget使ってるしw >>762 まあ、なんかセットアップでコマンド叩いたりするのだろう。そういえばwgetで認証できなかったら再入力なんて求められないよな...??あったかな?? wgetは--userと--passwordでユーザー名とパスワードを指定できるはずだけど httpのBASIC認証やftpのならそれで問題はないよね。普通にBASIC認証でそのオプションを教えてっていうことだけかな wgetが書かれたシェルスクリプトを呼び出すシェルスクリプトを書きたいように見えるが… まあ質問が日本語的に不自由すぎるね ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.1 2024/04/28 Walang Kapalit ★ | Donguri System Team 5ちゃんねる