シェルスクリプト総合 その28
シェルスクリプトの総合スレです。 □お約束 ・特記なき場合は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に逃げずにシェルスクリプトで処理するのが頭のいいやり方。 質問に対して問題が間違ってるといちゃもんをつけるのもやめましょう シェルスクリプト総合 その27 https://mevius.5ch.net/test/read.cgi/unix/1525337663/
FAQ Q. 秘密結社シェルショッカーってなんですか? A. しらん。どっかの変態団体やろ。近寄らんほうが良い。 Q. USP友の会ってなんですか? A. しらん。どっかの変態団体やろ。近寄らんほうが良い。 Q. シェル芸ってなんですか? A. しらん。ヲタ芸みたいなもんやろ。恥ずべきものや。 Q. ユニケージ開発手法ってなんですか? A. しらん。所でアプリの開発には普通のプログラム言語使ったほうが良いぞ シェルスクリプトの総合スレです。 初心者、学生、アマチュア、プロ、シェルの種類や OS を問いません。 スクリプトのお勉強・自慢・腕試しなどにどうぞ。 まずはテンプレートをご覧下さい。 ★A. お約束 1. 特記なき場合は #!/bin/sh がデフォルトです。この場合可搬性に注意し、 Traditional Bourne Shell もしくは、POSIX 相当のスクリプトでお願いします。 bash / zsh / ksh / ash / dash や OS 等に依存する場合は、明示しましょう。 良く分からない方は、使用している OS を書いておけば OK です。是非ご参加下さい。 2. 質問する前に、まず自分で調べましょう。ただし、 「聞くは一時の恥、聞かぬは一生の恥」です。積極的に参加しましょう。 3. 相手を侮辱する発言、失礼な発言は差し控え、知的な議論を楽しみましょう。 4. 他者には様々な環境や事情、目的が有る事に留意し、無下に扱う様な発言は 控えましょう。 ★B. お約束の補足 1. macOS では、/bin/sh の実体は bash です。また、一般的に BSD 系 や GNU/Linux の方は、/bin/sh がシンボリックリンクですので、注意して下さい。 ls (ハイフン)l /bin/sh や readlink -e /bin/sh で確かめて下さい。 2. 可搬性については、下記 F.1 を参照して下さい。 3. POSIX については、man 7 standards や下記 F.2 ( の特に Shell & Utilities ) を参照して下さい。 4. Traditional Bourne Shell とは、UNIX Version 7 から SVR4.2 の /bin/sh を元に 小さなの改変を加え主に商用 UNIX で残されているものです。( 下記 F.3 参照 ) 5. Traditional Bourne Shell で入手しやすい sh は、後期 SVR4.0 から派生し、 SunOS 5 / OpenSolaris を経た、Heirloom Bourne Shell です。 SVR4 / SVID3 相当です。同様の Unix utilities も扱っています。 ( 下記 F.3 参照 ) ★C. 初心者へのアドバイス 1. シェルスクリプトのことをシェルってゆーな 2. 知らないコマンドが出てきたら man コマンドで調べましょう。 3. UNIX には、シェルスクリプトに便利な小さなコマンドが色々あります。 apropos ないしは man -k でそれらしい単語による簡単な検索もできます。 4. シェルの構文や内部コマンドは man sh で。英語は LANG=C man shで。 5. 思い通りに動かないときは、まずは #!/bin/sh -x でトレースしましょう。 6. 適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも awk / perl / javascript / ruby / python 等、他の (スクリプト) 言語の方が 適した処理にはそちらを使いましょう。 7. シェルで使えるワイルドカード等は正規表現ではありません。 正規表現の話題は正規表現スレへ 8. csh / tcsh のシェルスクリプトは推奨されません。理由は下記を参照 http://www.speech-lab.org/ ~hiroki/csh-whynot.euc 9. cat file|すんなハゲ a. 詳細は "Useless Use of Cat" UUOC で検索して下さい b. 有用な場合も有ります Useful use of cat(1) 英文 http://www.in-ulm.de/ ~mascheck/various/uuoc/ ★D. シェルスクリプトでよく使うコマンド 1. 制御・条件判定系: [, test, expr, true, false, yes, getopts 2. テキスト処理系: cat, awk, sed, tr, sort, uniq, grep, wc, head, tail, cut, paste, comm, join 3. ファイル検索系: find ( スペースなどを含むファイル名を正しく処理するため、 find は -exec command {} + を推奨。 他に -print0、xargs は -0 オプションという方法もあるが Solaris 非対応 ) 4. ディレクトリ系: basename, dirname 5. 出力系: echo, printf 6. 対話コマンド制御系: expect 7. http / ftp の処理自動化: wget, curl ★E. 学習用テキスト 1. Bourne Shell自習テキスト ( 1993年 ) pdf お薦め http://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/sh-text/sh/ (↑サイト消滅かも) http://ayapin.film.s.dendai.ac.jp/ ~matuda/Lecture/PDF/sh-two.pdf 2. UNIX FAQ LIST http://www.nurs.or.jp/ ~asada/FAQ/UNIX/UNIX.FAQ.html (3. シェルを使おう - 導入からプログラミングまで - ( 2002年 ) http://www.netfort.gr.jp/ ~tomokuni/lms/shell/ (リンク切れ)) ★F. 参考リンク 1. 可搬性関連 a. autoconf マニュアル 移植性のあるシェルプログラム http://www.gnu.org/software/autoconf/manual/autoconf.html#Portable-Shell http://www.geocities.jp/fut_nis/html/autoconf-ja/Portable-Shell.html b. Portability talk [Bash Hackers Wiki] 英文 Obsolete and deprecated syntax も見る価値有り http://wiki.bash-hackers.org/scripting/nonportable c. How to make bash scripts work in dash 英文 http://mywiki.wooledge.org/Bashism d. DashAsBinSh 英文 https://wiki.ubuntu.com/DashAsBinSh e. Portable Shell Programming 英文 http://www.in-ulm.de/ ~mascheck/various/portability/ 2. POSIX The Open Group Base Specifications Issue 7 IEEE Std 1003.1, 2013 Edition 英文 http://pubs.opengroup.org/onlinepubs/9699919799/ 3. Traditional Bourne Shell 関連 a. The Traditional Bourne Shell Family History and Development 英文 http://www.in-ulm.de/ ~mascheck/bourne/ b. BourneShell / Where does the Bourne shell live? 英文 http://mywiki.wooledge.org/BourneShell c. The Heirloom Bourne Shell 英文 http://heirloom.sourceforge.net/ 4. マニュアル a. The Base Specifications Issue 7, 2013 Edition 英文 http://pubs.opengroup.org/onlinepubs/9699919799/nfindex.html b. FreeBSD 日本語マニュアル検索 http://www.jp.freebsd.org/man-jp/search.html c. JM Project (Japanese) http://linuxjm.sourceforge.jp/ 5. FAQ 等 a. UNIXの部屋 ( 2011年 ) http://x68000.q-e-d.net/ ~68user/unix/ b. Linux JF (Japanese FAQ) Project http://linuxjf.osdn.jp/ c. Advanced Bash-Scripting Guide 英文 http://www.tldp.org/LDP/abs/html/ d. Unix Programming FAQ 日本語訳 ( 2000年 ) http://www.race.u-tokyo.ac.jp/ ~moro/unix-programmer/ 移りたくない理由って、前スレで自演荒らししてたからってのしか思いつかない。 このスレを使いたい人間ってのが荒らしだとしたら、このスレを捨てるのが適切では? >>13 移りたくないのであれば、前スレで反論する機会があったのに、 一言も反論せずにいきなりこのスレを建てたんだから、 どう考えてもあなたがスレ荒らしでしょう。 移りたかった奴らがいつまでも見てんなよ ここを荒らすな ここのことは忘れて移った先で楽しく過ごしてください もう構わないでね >>17 荒らしスレであることを知らずに迷いこむといけませんから、 知らずに書き込んだ可能性がある場合には、重複スレである旨の 注意書きを今後も投稿するつもりです。 荒らしスレであることを承知の上で書き込んでいるケースについては、 私は今後このスレに書きこみません。 他の人がどうするかは私には分かりませんが。 向こうのスレで、こっちにしつこく誘導しようとしてるなら非難されて仕方ないけど、そんなことしてる奴いないんだろ? 見てないから知らんが もうここは構ってくれなくていいって 余計なお世話だわ どんだけ暇人だよ fishをログインシェルとして使ってます zshの場合bindkey "\e[A" history-beginning-search-backward-end で数文字入力して上矢印キーを押すと直近の履歴から保管されますが fishでこれをしたい場合どうすればいいのでしょうか? fishだとデフォルトで右矢印キーがこの動作になるようですが これを上矢印キーにしたいところです。 ~ > bind|grep search-back bind \e\eOA history-token-search-backward bind \e\e\[A history-token-search-backward bind \eO3A history-token-search-backward bind \e\[3A history-token-search-backward bind \e\[1\;3A history-token-search-backward bind \e\[1\;9A history-token-search-backward bind \e. history-token-search-backward bind \eo history-token-search-backward wgetを使ってシェルスクリプトでダウンロードツールを作ったんだけど ナロー回線だから出来るだけ無駄を省きたくて -cオプションで既存ダウンロード分に追記する形にしてる でも当然ならがコマンドが2重に発行されたらぐちゃぐちゃになるから psコマンドでwgetを2重発行しないようにしてるけどちょっと不安 実際一部の文字がpsコマンドで「?」表示されてgrepに掛からなかったことがあり ファイルが壊れたことがあった ぶっちゃけダウンロードしてるのはニコニコの動画であり (動画なんで視聴しないと壊れてるのかわからず厄介) ID_タイトル.mp4とかの形式で保存してるんだけど 問題はマルチバイト文字のタイトルだから 「grep "${id}.*${extention}"」として回避 実際はもうちょっとコマンドの詳細まで見てるけど こんな場合のベストってダウンロード先のファイル名に プロセスID(wgetを実行するシェルスクリプトのプロセスID)を含めるようにして 状況に応じてファイル名を変えながらwgetするくらいしかないのかな? 既存ダウンロード分のmvに成功したらwgetするとかで ファイルをロックする相当の処理を実現するイメージなんだけど ちなみにナローじゃない回線を使うことがあったり ダウンロード中に止まることがあるため 複数の動画を同時並行でダウンロードするつくりにしているため この問題はぜひとも回避したいです >>22 >複数の動画を同時並行でダウンロードするつくり なんでlockファイルで二重起動を防止しないのだろうと思ったら、 同時並列でwgetを実行したいけど、 1つの動画については多重実行されないようにしたい、ということか。 ニコニコのことはよく知らないけど、半角英数のIDが存在するなら、 wgetのダウンロード開始時に動画のIDのみを参照ファイルに書き込んで、 終了したらそのIDを消すようにして、IDが参照ファイルに書かれている間は、 そのファイルをダウンロードしないという仕組みにすればどうだろう。 でもそもそも > 実際一部の文字がpsコマンドで「?」表示されてgrepに掛からなかったことがあり これが分からん。idのみでgrepしたら文字化けしていてもヒットすると思うけど。 >>22 ファイルがオープンされているかを調べれば良いと思う どうやるのかな lsof が使えるなら lsof -a -c '/^wget$/' "${filename}" > ニコニコのことはよく知らないけど、半角英数のIDが存在するなら、 > wgetのダウンロード開始時に動画のIDのみを参照ファイルに書き込んで、 > 終了したらそのIDを消すようにして、IDが参照ファイルに書かれている間は、 > そのファイルをダウンロードしないという仕組みにすればどうだろう。 参照ファイルを参照してIDが無いことを確認してID書き込むまでの間に 同じ処理が走ったらチェック抜けてしまうなというのが懸案としてあります なのでダウンロードしているファイルそのものをロックファイルにして しかもmvコマンドの成否によって判断したらよいのではと午前中に思いました > でもそもそも > > 実際一部の文字がpsコマンドで「?」表示されてgrepに掛からなかったことがあり > これが分からん。idのみでgrepしたら文字化けしていてもヒットすると思うけど。 今はIDと拡張子でgrep掛けてるので問題ないのです (直近だと「禁書目録」がpsコマンドで「禁??録」になりプロセスチェックをスルーしていました) でも先の参照ファイルと同じで 同じ動画に対してほぼ同時にダウンロード処理が走った場合 psコマンドを実行してから実際にwgetコマンドを実行するまでの間に チェックを抜けてしまうことが考えられるのでどうにかしたいなと思ってます ちょっと後出しになって申し訳ないですが ダウンロードの処理はさまざまな状況で実行されることがあり これからダウンロードするぞってターミナルからコマンドを打つこともありますが cron登録していて自動でダウンロードが走るようにもしているため そういう適当な運用でも回避できればと考えています >>24 ありがとうございます 試してみたいと思いますが lsof でチェックしてオープンされていないと判断して継続のwgetがオープンする間に 並行して実行された処理でwgetがオープンしてしまう可能性があるので・・・ シェルでやるには難しい処理でしょうか? >>22 >>1-15 あたりをご覧になると分かりとおり、 このスレは荒らしが立てて維持しています。 特段の理由がなければ本スレ http://mevius.5ch.net/test/read.cgi/tech/1532397676/ の利用をお勧めします。 サーバーのサービスではなく、 ユーザは自分1人だよね。cronも動いているけど。 それなら、ミリ秒単位で処理開始がぶつかることなんて想定しなくてもよいのでは。 人命がかかっているような処理なら別だけど。 >>28 確かにそうですが方法が確立し実装してしまえば 動画を視聴してチェックと言う作業からほぼ解放されるので もうちょっとやってみます >>27 実装を試して相談したいことがあった場合検討してみます ずっと楽をするために今努力して作りこむってのは間違っていない まあ出来ないと思うときは妥協は必要だが >>26 ファイルに対応する「ロックファイル」を作って、その存在確認をするのが定石だったみたい 既にロックファイルが存在していたら、別のプロセスがファイルを使っていると見做す その際ロックファイルの存在確認と作成を「同時」(アトミック)に行うのが大事だそうで そのファイル、安全にロックできていますか?(アトミックなファイル操作:後編) https://heartbeats.jp/hbblog/2013/10/atomic03.html こんな感じかな lockfile="${outputfile}".lock if ln -s -- $$ "${lockfile}" 2>/dev/null; then ( unlock() { rm -- "${lockfile}"; } trap "unlock" EXIT HUP INT QUIT SEGV TERM wget -c -O "${outputfile}" "${url}" ) & fi $ yotei.py 201808290900 って感じでスクリプトの引数に今日の年月日0900(date +%Y%m%d0900)を入れて実行したいです。 cronで実行したいのですが、date +%Y%m%d0900の出力をyotei.pyの引数に入れるには、1行でどうやって書いたらいいですか? $ yotei.py namae 201808290900 だったので、2番目の引数にdate +%Y%m%d0900の出力を入れたいです。 すぐ思いついたのはシェルスクリプトを1個増やして以下のようにする export ymd0900=`date +%Y%m%d0900` yotei.py namae $ymd0900 それをcronから呼ぶ >>34 >>35 どうもありがとうございます! ファイルを増やしたくなかったので1行でやりたかったんですが、ウィキペディアのその項目のとおり、エスケープ\を入れる事で1行で出来ました! yotei.py 名前 $(date +\%Y\%m\%d0900) サマータイム導入に気をつけろよ ローカルタイム使ってると同じ日時が 2回でてくることになるぜ EUじゃサマータイムは廃止だっていうのにマジで日本はこれから導入するのか? 趣味でプログラム作ってるだけなのに余計な処理増えるのはホント困る…。 >>22 youtube-dlならニコニコにも対応してるしタイトルとIDそのままで保存できるよ 但しここ数年の動画はDL速度が極端に遅い上に途中で必ず落ちる [download] 5.6% of 202.83MiB at 98.22KiB/s ETA 33:15[download] Got server HTTP error: Downloaded 12014750 bytes, expected 212678720 bytes. Retrying (attempt 1 of 10)... ERROR: unable to download video data: HTTP Error 403: Forbidden 永続リトライ設定でもこうなるししmpvでも再生中断するからな 昔のflvなんかは高速だけど年代で仕様が違う辺りエロサイトより酷い 東京オリンピックまでにサマータイム導入 てのはどう考えても物理的に不可能だから 話は立ち消えになるだろうけど、将来、 導入されないとも限らない ローカルタイムを出力するときは必ず timezoneを付けておいたほうがいい >>40 YAGNI。必要になってから対応するよw >>42 このスレ立てた奴が荒らしに行ってるからな。 あっちの板に嫌がらせで重複スレまで立てるという性格の悪さ。 そういう悪人の立てたこのスレ使ってると、悪人の一味みたいな立ち位置に属することになるぜ。 >>43 要件による。どうしたらいいかは客にでも聞いてこい なんのためにプログラム板に移動したんんだっけ? 人を増やすため? >>47 前スレで荒らしが出たからIDやワッチョイをつけたかったんだけど、 UNIX板ではつけられなかったから。 で、荒らしはIDつくのが嫌で新スレが立った後からこのスレを立て(>>10-15 )、 さらには新スレを荒らしに行ってるってのが現状。 でもIDつくのが嫌だったんでしょう? IDつくのが嫌じゃなくなったってこと? >>49 IDつくと自分が荒らしてることが分かるから嫌だったけど、 向こうのスレについてはスレ自体を敵視しているから、 自分が荒らしてることがバレバレであっても、スレを使いづらくしたい ってことじゃないかな。 >>51 ム板の本スレは意図的に荒らしてて(だからバレてもOK)、 前スレは天然で荒らしてる面がある(だからバレたくない) って程度の違いはありそうだね。 >>52 いやいや、単に荒らしは最初から隠すつもりもなく、 バレようがバレまいが関係ないんだよ。 荒らしにとってはは最初から隠してるわけでもないが、 でもこのスレの住民がその荒らしのIDを見たくて移動したんでしょ? それでんで、見て何がしたかったのか不明だけどなw IDが出ていれば荒らされないとでも思った? IDを何に使うかなんて自明でしょ。 まさか分からないってことはないよな? 荒らしをNGIDにして見えなくするため、という説がある 確かにNGIDにすると見えなくなるが、 荒らしの書き込みを止めることはできない 荒らしはどんどん自分の意見を書き込むが それに対しての反論はできない。 なぜなら荒らしの書き込みが見えないから 荒らしとNGIDに入れてない人とのやり取りでスレは埋まっていく はたから見れば、話についてこれず時々レスするが 荒らしに論破され何も言い返せない構図のできあがり それ全体の荒らしの濃度が高まる そしてIDは変わるから毎日の登録作業が増える。 忘れるとついレスをしてしまう というわけで、以下のどっちかの運用にするのがよくあるパターンだな。 ・このIDは昔から粘着してる奴だから無視するぜってコメントを時々入れつつ無視する ・奇特な人物がいちいち反論するので、スレにいる他のメンバーは、連鎖アボーン設定して安心してその議論全体を無視する IDがないとこういう回避ができないから、ひたすら我慢することになる。 連鎖あぼーんって荒らしが誰だれかれ構わずレスしたら みんな消えちゃうの? まあ回線切ってIPアドレスを変えればいいだけだしな つまりIDやIPアドレスを変えてNG避けする意志のある荒らしってことだから、 IPアドレスも表示させるようにして、 IPアドレスの範囲を使ってNG登録するのもやむなしってことだな。 今でも2つのプロバイダーを使い分けて自演してるって 自分でバラしてたから、NG登録する範囲も2通りは必要だと。 特定文字列の除外リストを元に除外処理をしたいんだけど リストとかあきらめてgrepをフィルタファイルとして別するのが一番楽? やりたいのは以下のようなことなんだけど シェルスクリプトなのにプログラミング的なことやって grepのフィルタを組み立てることに違和感を感じてる(面倒とはっきり言えって?) echo ${DATA_REC} | grep -e AAA -e BBB -e CCC if [ $? -eq 0 ] then continue fi # 継続処理 > grepをフィルタファイルとして別するのが一番楽? ってのはファイルにgrepのコマンドを書いてreadで読んで echo ${DATA_REC} ${grep_cmd} とかにするってことね grepコマンドが書かれてたら適用 書かれてなかったらスルーって感じ ああパイプがうまくいかないから若干判定が必要か・・・ pi@melchior /tmp $ export grep_cmd=" | grep -e AA -e BB" pi@melchior /tmp $ echo AAA $grep_cmd AAA | grep -e AA -e BB pi@melchior /tmp $ echo AAA | $grep_cmd -bash: |: command not found pi@melchior /tmp $ export grep_cmd=" grep -e AA -e BB" pi@melchior /tmp $ echo AAA | $grep_cmd AAA pi@melchior /tmp $ もうベタで書いてしまった・・・ でも順調!すげーよく動いてる! この件は今後の課題にしよう 除外する文字列をファイルに入れて grep -f か grep -v -f でいいような気がする >>66 > シェルスクリプトなのにプログラミング的なことやって シェル芸じゃなくてスクリプトなんだから プログラミングで当たり前だよw >>67 少し考えてみたが、俺もgrepの-fオプションを利用するのが一番楽だと思うな ただ昔、除外リストの否定とかやりたかったんで書いたことはあるが grep -f 使えばいいから不要だが お手軽に>>66 のようなことをするのならこうかな リストにスペースなどが入っていたらうまくいかんがw 文字列の組み立ての参考として echo ${DATA_REC} | grep $(printf ' -e %s' $(cat list)) シェルスクリプトじゃなくてシェルの基礎を訊いてアレだけど bashの$()と``って使い分けた方がいいの? 端末ではバッククォート多用してるけども ``は古い書き方。ネストができないという欠点が有る bashに限らず、$()を使ったほうが良い。欠点は文字が一文字多くなるだけ きっちりエスケープすればネストはできるよ。もちろん推奨はせんが test $(date +%w) -eq 5 今日が金曜日なら5が出るんですが、-eq というのはコマンドなのかtestコマンドのオプションなのか、これは何ですか? 自己レス -eq はtestコマンドのオプションで、==の事みたいですね test コマンドのオプションです。 ところで今日は金曜日ですが5は出ませんよね。 戻り値は0となりますが……何か勘違いしている気がします。 すみません test $(date +%w) -eq 5 && echo "今日は金曜日!" これだと、金曜日だとechoが実行されました >>82 自己レス 金曜日かどうか調べて金曜日なら戻り値は0、 で、戻り値が0の場合echoが実行されるって事ですね 毎月第2月曜日と毎月第2週の月曜日とでは、指す日にちってもしかして異なります? 0 17 8-14 * test $(date +%w) -eq 5 && command こんな風にcronで毎月第2金曜日とか指定したいんですが、 例えば今月の5日で言うと、5日は1回目の月曜日だけど、月の2週目にあるので疑問に思いました。 0 17 8-14 * test $(date +%w) -eq 1 && command これだと今週の月曜日には実行するされないですよね? 読みづらい。testなんて使うな [ $(date +%w) -eq 5 ] && echo "今日は金曜日!" >>85 [ ]ってなんですか? ググろうにも記号なのでググれないです bash(バージョン 4.4.12(1)-release)でスクリプト書いててちょっと謎が $ a=1; b=2; [[ ${a}<=${b} ]]; echo $? こうするとちゃんと終了コードの0が返ってきますが $ a=1; b=2; [[ ${a} <= ${b} ]]; echo $? 比較演算子の前後にスペースを入れると「条件式に構文エラーがあります」「`${b}' 周辺に構文エラーがあります」と怒られます $ a=1; b=2; [[ ${a} < ${b} ]]; echo $? 比較演算子をleでなくltにするとまた0が返ります これって何故なんでしょう? >>88 [[ ... ]] で使える演算子に <= は存在しない それは数の比較ではなく [[ "1" < "=2" ]] という文字列の比較になっている なので <= の右に空白を置くと [[ "1" < "=" "2" ]] となりエラー 条件式 https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html#lbBW >>89 さっそくありがとうございます そうか、イコールをつけない不等号で上手く動いてるように見えるのは、文字列として辞書順で比較してるからなんですね どうやら私の頭の中では、二重丸括弧での算術式展開とゴッチャになってたみたいです 何時間も唸ってたのが一撃でスッキリしました。ありがとうございました >>87 もしかしてtestと[]はだいたい同じですか? testを使わない方がいいのはなぜなんでしょうか? >>87 それで出てくるのは /usr/bin[ の方のmanじゃないだろうか bash の場合。 $ type [ [ is a shell builtin $ help [ [: [ arg... ] Evaluate conditional expression. This is a synonym for the "test" builtin, but the last argument must be a literal `]', to match the opening `['. sedで\1を変数名としていっぺんに異なる部分を異なる変数の内容で変換できませんか? sed -e "s/<\(.*\)>/${\1}/g" こんなかんじの #!/bin/bash # 変数URL, ETAGには既に適切な値が入ってるとする OPT=('--header' "'If-None-Match: ${ETAG}'") curl "${OPT[@]}" "${URL}" こんなスクリプトを書いたけど、curlと鯖のやりとりを覗くと、リクエストヘッダのIf-None-Matchの行にシングルクォーテーションが付いて 'If-None-Match: (ETAGの値)' と送られてしまう。で、試しにcurlの行を echo "curl ${OPT[@]} ${URL}" > /tmp/tempfile . /tmp/tempfile と書き換えて実行すると、ちゃんと正常に動く。man bashを読んだりbashの引用符の扱われ方をググってみたりしても、何が何だかさっぱり分からない。 どなたか助けてくれませんか。 自己レス curlだからとか関係ないな。変数にシングルクォートで囲ったものが入ってて、それをダブルクォートで囲った配列展開してるんだから、そのパラメーターはそのままシングルクォートつきになって当然。 しかし、ETAGはダブルクオートを含むしhttpリクエストヘッダはスペースを含むから、全体をシングルクォートで囲まなきゃならんのだよな。 やっぱどのタイミングでどのクォートがどう展開されるのか、一段階ずつ追いかけてみるしかないのかな なんか混乱しとるなw まあ、ダブルクォートは、他言語を使っている人からすれば 直感に反する機能だってことに、俺も最近気づいたんだけどな ただどこがどう違うかを言葉で説明したことがわけじゃない。やってるみるか? ・シェルスクリプトは文字列として展開されて実行されているようでそうではない ・ダブルクォートは文字列を囲う機能ではなく、変数展開の挙動を変えるエスケープの一種 この二つに集約されるかなぁ > しかし、ETAGはダブルクオートを含むし これ関係ないんだわ OPT=('--header' "If-None-Match: ${ETAG}") だと OPT=('--header' "If-None-Match: "686897696a7c876b7e"") こうなってしまい OPT=('--header' "If-None-Match: " 686897696a7c876b7e "") のように解釈されると思ってしまうが違う。 別に文字列展開されてから、動くわけじゃない ダブルクォートは「 If-None-Match: ${ETAG} 」の部分を一つの引数として 扱いますよー(ただし中の変数は展開されますよ)という意味。 変数の中にダブルクォートが入っていようが改行が入っていようが関係ない またダブルクォートはそれだけの機能ではなく $@ が入っている場合に異なる挙動をする "$@" が入っている場合、一つの引数ではなく複数の引数として扱われる 例えば引数$1〜$5が存在する場合、"$@" は "$1" "$2" "$3" "$4" "$5" と等価 また"foo$@bar" となっていた場合、 "foo$1" "$2" "$3" "$4" "$5bar" と等価 引数が一つなら "foo$1bar" だし、引数がゼロの場合は、書かなかったのと同じとなる("" 空文字にはならない) このように文字列として囲う機能じゃなくて、中に入ってる文字や変数の解釈の仕方に影響を与える機能 ちなみに "$@" を複数の引数に展開されたくなければ "$*" を使う >>100-101 ありがとう。おかげで、サクッと片付きました。素直に OPT=('--header' "If-None-Match: ${ETAG}") curl "${OPT[@]}" "${URL}" で何の問題もなく動作しました。最初にcurlについて調べてたときにETAGを使う例でシングルクォートが使われてたのに、ずっと脳味噌が引っ張られてたようです。 上の行で変数に入れる時点で、スペースを含む一つの文字列として扱われてるんだから、あとはその中身がなんであるかに関係なく、"$[@]"で展開すればいいわけですね。 ありがとうございました。 bashでログ出力処理を一括でやるにはどうすれば良いですか? powesshellだと、Start-Transcript に対応するコマンドを教えてください >>103 何がしたいのかよくわからないが シェルスクリプト内の標準出力と標準エラー出力をファイルに出力するなら #!/bin/bash exec >script.log 2>&1 ... >>104 何したいかよくわからんって、 パワーシェルでいうStart-Transcriptをやりたいの bashで一行ずつリダイレクトつけないとダメとかダサすぎる PowerShellなんぞ興味が無いから知らんという人が多かろう 標準出力と標準エラー出力をファイルとコンソールの両方に出したいと言えばいい 知ってるがお前の態度が気に入らない(AA略) やっつけ $ { > echo foo > ECHO bar > } 2>&1 | tee result.txt foo ECHO: コマンドが見つかりません FreeBSD の /usr/bin/man で、 if { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1; then という記述があるんですが、これって何をしているんでしょう。 ・標準エラー出力を捨てている ・3 を 標準入力の指す先 (tty) に設定? ・0 を ↑の3に設定? 3>&1 して 1>&3 なら退避目的かなと思うんですが、これは違うので、 意図がわからないです。 ソースはここです。 https://github.com/freebsd/freebsd/blob/master/usr.bin/man/man.sh#L646 ・MANWIDTH=ttyのときはmanの標準出力1の横幅を取得したい。 ・sttyの操作対象端末は標準入力0で、出力先は標準出力1。 ・a>&b は dup2(b,a) のことで、左を使うと実体は右になる。 ・標準エラー出力2は捨てる。 という前提で、 sizes=$($STTY size 0>&1 2>/dev/null) と書くと、 sttyの標準出力1は$()に取られてるから、manの標準出力1とは別物になって、 正しい端末をsttyできない。 { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1 は、1が取られ てるなら3を中継すれば安全じゃねと書いたものと推測される。 { sizes=$($STTY size 2>/dev/null); } 0>&1 と書けば十分なはず。 findした結果を1行づつ配列に代入したい場合にはどうすればよいでしょうか? 当方が書いたshellだと、検索したい文字列に空白があるケースだと そこで要素が別れてしまいます。 array=$(find ${HOME}/animal -type d -iname "*検索したい文字列*") >>113 ありがとうございます! リダイレクトにstdin/stdoutの差し替え的な使い方があるとか、sttyはstdinを見るとか、sttyがstdinを見てもstdoutを見てもそれが端末を指しているなら同じこととか、数枚目からうろこが落ちました。 しかしそもそもsttyはデフォルトのstdin見ておけばいいんじゃね、とも思ったり。command |man 的な使い方ってあったっけなぁ。 少々スレ違いですがお許しください OS 組み込みの tcsh をバージョンアップしたいのですが、 シェルスクリプトの挙動が変わってしまうのが怖くて、なるべく コンパイル時オプション(configure オプション)を揃えたいのですが バイナリしかない場合に、コンパイル時オプションを調べる方法ってないですかね? ## 例えば ISC BIND の -V オプションみたいな ログインシェルでfishを使う時、 https://gist.github.com/mitukiii/4954559 できたらやり方教えてください $ myCommand タブキー押すと $ myCommand foo -- do foo bar -- do bar unk -- do toilet って候補と1行説明表示されて $ myCommand f でタブーキー押すと $ myCommand foo と補完される 方法を知りたいです これできたら重いzshから魚に乗り換えられる ここはシェルスクリプトのスレです。 シェルの使い方のスレではありません。 スクリプトの話をしてください シェルスクリプトだけで実装した一番高速なFizzBuzzはどんなものかとか 「使てる(つこてる)?」は「使っていますか?」という意味の質問であって、使用可能かどうかを聞いてる訳では無いのでは ほにゃらら ほんじゃらら かきく 0 あいう かきく 1 あいう かきく 2 あいう かきく 3 あいう かきく 4 あいう かきく 5 あいう さしすせそ と書かれたテキストファイルを作りたいです echo -e ほにゃらら"\n"ほんじゃらら > index.txt seq -f "%g あいう" 0 5 > index.txt ここまではわかったんですが、seqで連番を書き出す時に番号と番号の間の行に「かきく」を入れて最後の行に「さしすせそ」を加えるやり方教えてほしいです >>129 ありがとうございます 調べてみました cat > index.txt << "EOF" ほにゃらら ほんじゃらら あいう EOF seq 0 5 | awk -v 'ORS= あいう\nかきく\n' '{print $1}' >> index.txt echo さしす >> index.txt こうやると ほにゃらら ほんじゃらら あいう 0 あいう かきく 1 あいう かきく 2 あいう かきく 3 あいう かきく 4 あいう かきく 5 あいう かきく さしす と出力されました 最後から2行目の「かきく」を出さないやり方が分からないです 一応これでうまくいきました cat > index.txt << "EOF" ほにゃらら ほんじゃらら かきく EOF seq 0 5 | awk -v 'ORS= あいう\nかきく\n' '{print $1}' >> index.txt sed -i -e '$d' index.txt echo さしす >> index.txt >>132 自分のやり方はなだったらしそうなのでそのキーワード調べてみます えー、難しい... 俺>>129 はこんなもんしか考えてなかったけど awk 'BEGIN{print"ほにゃらら\nほんじゃらら";for(i=0;i<6;i++){printf"かきく\n%d あいう\n",i};print"さしすせそ"}' >>128 cat <<END >index.txt ほにゃらら ほんじゃらら $(printf 'かきく\n%s あいう\n' $(seq 0 5)) さしすせそ END あ、バックスラッシュが円記号になってしまった... cat > index.txt << "EOF" ほにゃらら ほんじゃらら EOF printf "かきく\n%s\n" {0..5}あいう >> index.txt これだと大分短くて出来たけど、数字と「あいう」の間にスペースが入れられない 被ってしまった みなさんありがとうございます 質問ぬしの自分は>>138 です 135と136のやり方調べてみます >>136 catで書き出すファイルの中でprintfをやって、そのrintfの中でseqで連番作るんでね これだとファイルへの書き込みは1回ですみますね >>135 これも> index.txtで終えれば1回ですみますね だけどawk難しいです がんばって135のやり方理解できるようにします >>140 > これだとファイルへの書き込みは1回ですみますね どんな方法で作るにせよ { } で括れば一回にまとめられるよ { printf '%s\n' 'ほにゃらら' printf '%s\n' 'ほんじゃらら' printf 'かきく\n%s あいう\n' $(seq 0 5) printf '%s\n' 'さしすせそ' } >index.txt >>141 こんな方法もあるんですね ありがとうございます curlの標準出力の6行目を変数に入れて他の文字列と組み合わせて標準出力に出力したいです。 URL="hoge" ROKU="curl -sS $URL | sed -n '6p'" echo "あいうえお"$ROKU"さしすせそ" しかし結果はこうなりました あいうえおcurl -sS hoge | sed -n '6p'さしすせそ >>142 続き >>141 さんで教わった{}を使えばよさそうな気がするですがエラーになりました printf "あいうえお" $ROKU #chomp のように\nを消すパイプ必要だと思う printf "さしすせそ" >>144 echoじゃなくてprintfなら改行されないからあいうえおに続けて書けますね だけど、このままだとROKUのところで改行されてしまうからさしすせそは2行目に来ちゃいますね >>128 > と書かれたテキストファイルを作りたいです こうすれば良いのでは? cat<<HERE > index.txt ほにゃらら ほんじゃらら かきく 0 あいう かきく 1 あいう かきく 2 あいう かきく 3 あいう かきく 4 あいう かきく 5 あいう さしすせそ HERE >>142 コマンドの標準出力を変数に設定したりコマンドの引数にしたりするには 「コマンド置換」 $(…) を使います あと、「6行目」以外の部分も取り出したくなったときに curl を何度も実行したくはないので curl と sed は分けておきたいところ するとこんな感じ PAGE=$(curl -sS "$URL") ROKU=$(printf '%s\n' "$PAGE" | sed -n '6p') NANA=$(printf '%s\n' "$PAGE" | sed -n '7p') printf 'あいうえお%sさしすせそ\n' "$ROKU" printf 'かきくけこ%sたちつてと\n' "$NANA" >>146 複数行書く方法ありがとうございます >>147 うまくいきました ありがとうございます $ bash -c 'unset a b;echo 10|read a;let b=a+10;echo $b' 10 この動作ってPOSIX的にはどうなの? 読みづれーなw bash -c ' unset a b echo 10 | read a # echo $a = 空 let b=a+10 echo $b ' letはPOSIXにない readはサブシェルなんだからaは空に決まってる ごく普通の正しい動作 正しいコード bash -c ' unset a b echo 10 | { read a let b=a+10 echo $b } ' letまで考えて無かったすまん まあ説明の為なのでそこは目をつぶってくれたまい opensuzeなんだけども $ ksh -c 'unset a b;echo 10|read a;let b=a+10;echo $b' 20 $ この動作ってPOSIX的にはどうなの? curlのやり方教えてください ブラウザのフォームにjsonを書いてポストボタンを押すとokが出るけどターミナルからcurlでやろうとすると、ボディが空だとなり送信出来ません 書き方間違えていますか? https://i.imgur.com/Nvm7CMj.jpg ブラウザの開発ツールからcURLでコピーした方が早そうだぞ >>155 どうもありがとうございます -H 'Content-Type: application/json' を付けたら動きました アプリの起動判定をしたいんですが ps -alxw | grep アプリ名 2行より多ければアプリが起動してるんだと思いますけど確実な方法ありますか? >>158 どうもありがとうございます そのコマンドで何も変えらなかったら起動中という事であってますか? 起動してないとわかっても、その直後に起動することも有るから ロックを掛けないと確実にはならないけどな >>160 どの環境でも使えるロックの機構ってなにかある? 怒らないで教えて欲しいんだけど何でお前らPowerShell使わないの? 今やPowerShellの方が勉強会でドヤれるしちょまどなんかもPowerShellだってよ >>164 Dockerのalpine、debianなど、ほぼすべてのイメージでことごとく動かないから。 shで十分なのに、PowerShellなんて使いませんよw >>164 linux のコマンド群が使えないから ソースコードをダウンロードしてビルドしようとしたら… ERROR: You must either be root or be able to use sudo ビルドするのに root になれって? この時点で話にならないよ。 >>168 エラーメッセージには「sudo を使え」と書いてあるが とりあえず適当なことを言ってPowerShellを 貶めたかったんだろ?バレて逆効果になってるがw grep 等の外部コマンド?を使わずに任意の文字列の最初に見つかる3桁の数字を得る方法があれば教えて下さい (例えば、abc_4_de_99_fgh_ijklm_no_567_2_123_pqrst_uvwx_yz だと567) bashなら=~と、$BASH_REMATCH使えばできるんじゃね >>173 おまえは俺かw 似たようなことをやったよ。grepで(笑) 外部コマンドを使わないなら、こうなるから面倒くさいんだよな。 できるけど面倒くさい。だから遅いけどgrepにした。 v=abc_4_de_99_fgh_ijklm_no_567_2_123_pqrst_uvwx_yz v=${v#"${v%%[0-9][0-9][0-9]*}"} v=${v%"${v#[0-9][0-9][0-9]}"} シェルスクリプトだと(bash依存は知らん) マッチした部分を含めて削除はできるけど マッチした部分を残したその他を削除が簡単にできないんだよね。 だから「マッチした部分を含めて削除」したら残りが 「マッチしなかった部分」になるのを利用して、 改めて全体から「マッチしなかった部分」を取り除くというのを前後でやればできる。 ありがとうございます 面倒でも前後から不要部分を取り除くしかないのですね >>178 ${v%%[0-9][0-9][0-9]*} ってかいてあるやん abc_4_de_99_fgh_ijklm_no_567_2_123_pqrst_uvwx_yz ・・・(1) ↓ ${v%%[0-9][0-9][0-9]*} abc_4_de_99_fgh_ijklm_no_ ・・・(2) ↓ (1)ー(2) 567_2_123_pqrst_uvwx_yz ・・・(A) ↓ ${v%"${v#[0-9][0-9][0-9]}"} _2_123_pqrst_uvwx_yz ・・・(B) ↓ (A)ー(B) 567 今更だが>>179 は × ${v%"${v#[0-9][0-9][0-9]}"} ○ ${v#[0-9][0-9][0-9]}" だな それらをPowerShellで書くとどうなるか? 一度でも考えてみたことはありますか? PowerShellで書くとLinuxで動かすのが大変になります。 5年くらいするとセキュリティパッチが出なくなって使用禁止になるから また作り直しになるんだろうどうせ。 例えば中身が 3,soba,inarizusi,hishimoti,ushioziru ... のcsvファイルなら最初の数字が3なので以下の文字列の3番目をつないで soBa inArizusi hiShimoti usHioziru ... でbash ... というように csvファイルの最初の値で以降の処理が変わる場合はどうすればいいでしょうか? 一度ファイルを最後まで空読みすれば簡単なのですが、読み込みは1度で終わらせたいです。 >>185 なんでそんな分かりづらい説明するんだ? >>185 引数で単語と数字nを受け取ってn文字目の単語を返す関数を書けばいいだけ >>189 日本語ではなくてbashでお願いします!! >>188 結果だけ見たら 入力テキストをカンマで区切って 最初の数値を取得 ⇒ nとする 残りの文字列のn番目の文字をアッパーケースに変換して空白区切りで連結する かな 俺ならテキストが小さいならBashで一気に読んで処理すればいいと思うしでかいならPythonとかで処理する > 俺ならテキストが小さいならBashで一気に読んで処理すればいいと思うしでかいならPythonとかで処理する これはなんで? 小さいとかの境目はどれくらい? そんなこと聞いてくるようではセンスがないよ センスがない奴にいくら説明しても無駄 pythonだと単語のn文字目を取り出すなんて朝飯前だしな 関数書く手間が一つ省ける 疑問になった点は「テキストが小さいなら」です。 その他の話は聞いてません。 > pythonだと単語のn文字目を取り出すなんて朝飯前だしな 単語の3文字目(オフセット2から1文字)を取り出す echo "${str:2:1}" Pythonだとどう朝飯前なんですか? 早く答えのスクリプトを書いてください!! 遅いですよ!! >>195 個人的には今どきなら1MB以下なら小さい1GB以上ならでかい その間ならケースバイケース PCの性能やメモリ容量とかと相談 >>185 > 一度ファイルを最後まで空読みすれば これはどういうスクリプトなの? >>198 1MBってことは、1行256バイトとして4096行以下なら小さいってことですね。 10MBで約4万行、100MBで約40万行、1GBで400万行 昔のExcelの制限が1シート65000行だったことを考えると エクセルで扱えるデータなら問題なさそうですね アスペかよw アスペならちゃんと改行コードも数えるんだぞ? >>201 お前なんのためにレスしたの? >>200 が言ってることは正しいし、お前の主張は何も含まれていない。 ただ、レスしただけ 185です。説明不足ですみません。 やりたいことは1行目を読み取り、2行目以降はそのままwhileループで最後まで読みたいのです。 ただそのためだけにフラグを使うのもなんだかなぁと。 わざわざ空読みする理由が分かんねえ 今出来てる状態のスクリプト貼って何がうまく行かないのか説明してみ >>205 そこまでは上手く書けてる その調子で頑張れ >>190 今日一番ワロタ キミもbashで質問しなよ bash は重複しない4文字である。つまり2bitのデータと考えられる 日本語を1文字16bitのデータと考えると、 1文字をbashの4文字×8組=32個のデータで表現できる つまりbashで質問すると32倍のデータが必要になる 1レスに2048バイト、1024文字を書き込めるから32文字の質問であれば bashで質問することは可能 >>208 > 1文字をbashの4文字×8組=32個のデータで表現できる この行から間違えてるだろ >>199 こいうんじゃね? というのを期待してた?残念w >>211 while IFS=, read は思いつくけど 最後まで空読みってどんな処理なのか気になっただけ >>196 >>> str = "foobarbaz" >>> print(str[3]) b python3は重いかわりに色々便利なのが定義されてる タブで字下げされてるテキストファイルの中にある _TAG("S.T.A.R.T") が含まれる行と _TAG("E.N.D") が含まれる行との間にある行数を数えるにはどうすればいいでしょうか ...... | sed -n '/_TAG("S.T.A.R.T")/,/_TAG("E.N.D")/p' | wc -l こんな感じ さんくす sedやwcなどの外部コマンド?を使わない方法はありますか? >>216 そういうことするなら perl5に行きなよ 普通はそれも最初から入ってて、文字処理に強い言語だから --- そんな処理だと、その処理の前に タグがネストしてたり、正しく対になっているのか調べれた方が安全 おみあげに類似したコードあげる https://ideone.com/XCz8Ou 対が壊れてたら -1 を 壊れてないならネストの最大の深さを返す >>214 問題の意図が明確 その _TAG("S.T.A.R.T") とかは字下げされているのかどうなのか _TAG("S.T.A.R.T") が含まれてると言うが、 一行 は _TAG("S.T.A.R.T") だけではないのか? echo ' _TAG("S.T.A.R.T")' なんかも考慮する必要あるのか? 俺だったら一行まるまる、_TAG("S.T.A.R.T") だけにするがな その方がパースしやすいので あと _TAG("S.T.A.R.T") は複数あるのか?という質問も追加 ネストされている場合は考慮するのか?とか まあいずれにしろテキストファイルは read で読み込めるんだから こんな感じになるだろうが while IFS= read -r line; do case $line in '_TAG("S.T.A.R.T")') なんとか ;; '_TAG("E.N.D")') かんとか ;; esac if 条件; then count=$((count + 1)) fi done < テキストファイル >>218 みたいにそういう場合だったら Perl にとかいうやつがいるけど シェルスクリプトで同等のコードを書いても大差ないんだけどなw sedやwc使うなとかいう制約も謎だわ 言語やツールが何であれ結局裏で似たようなライブラリの関数呼び出すのに 理由がわからないなら普通に聞けばいいだけなのに。 自分が知らないだけなのに、なんでそんなことありえない、 あってたまるかみたいな書き込みをするんだろうねw 理由がわからないんじゃなくて、そんなことを言い出す人間が理解できないって話だよ こだわりがあるならこんなところで人に聞くんじゃないよって話で 自分とは違う方針の質問は受け付けない そんなレスはこてんぱんにしてやる。ですか? 自分の期待とは違う方針の回答は受け付けない そんなスレはこてんぱんにしてやる。じゃないの? >>227 スレの流れ見たけど受け付けられてるじゃん 宿題を済ませたいのか知らないが 人に聞くくらいなら針路変更したらどう? 知り合いにコンピューターの勉強してた人居るけど 大学で課題をすべて友人からパクってたそうだ 今その人バイトで食いつないでる ITの仕事できたら低くても年収400万は行ったろうにね >>229 知り合いの人は大学をやめて会社を起こして金持ちになったよ。 お前が何をいいたいのか知らんが >>228 さんくすとお礼を言った上に、条件をつけ忘れてたから 補足しただけでしょ たったそれだけで、はぁ?理解できない。謎だわ。なんでそんな事するの?バカなの? みたいに言うのはなんで? >>230 知り合いは宝くじ当たったよ 中卒、高卒、大卒の平均年収見てみ 問題を解決できないやつは 学歴がなんでも大成しないな 2chは口が悪いやつが多いけど ここ見てると分かるように無償で相手してくれるやつがいるんだな 現実はどうだろう そんなことないよ 社会に出れば分かるがフリーライダーは受け入れられない 街角でスケッチブックに助けてくださいって掲げるのか? そんなの通報されて終わるよ SNSなら答えてくれるって? フォロワーも居ない人の相手なんて誰もしない 要するに2chしか質問する先がないんだ >>231 何で逆切れするの? 仕事は自分でしましょう >>231 >>227 があなたの書き込みなら あなたが煽っただけでしょう そして>>227 があなたではないなら なぜそんな反応するのか分からない 課題か仕事か知らんが問題を片付けてくれたのになぜ素直になれないんだろうか 仕事だったら出来上がらないから検収されずに報酬もらえないぞ JavaHouseってのがあって明らかに仕事に関係するであろう質問してた輩に 運営者の人がそれ幾らなのって聞いてたな 聞いた本人は無料ですってなんか意味の分からんこと言ってたが 課題をこなせず大学をやめて成功したって丸投げ派遣会社でも設立したんか >>240 人の話がシェルスクリプトと何の関係があるのという話だ 人の話をし始めたやつにいえな >>243 全ての質問に対してそういう回答をしてるなら何も言わんよ >>230 まあ今どきの日本人はだいたいビル・ゲイツは知り合いだからなw >>244 でたでたw なぞの平等理論w あいつだけずるいとかいう妬みで周りが見えなくなってるんだろうなあ 自分なら質問者が 「今こうやってるけどもっと効率のいい方法ない?」 とか聞いてきたら答えてあげたくなる 一度答えてそーじゃねーよとか言われたら・・・w 一度答えてそーじゃねーよと言われたら? ↓これみて「そーじゃねーよ」言われたと思っちゃったの? 215 名前:名無しさん@お腹いっぱい。[sage] 投稿日:2020/04/11(土) 11:20:47.30 ...... | sed -n '/_TAG("S.T.A.R.T")/,/_TAG("E.N.D")/p' | wc -l こんな感じ 216 名前:名無しさん@お腹いっぱい。[sage] 投稿日:2020/04/12(日) 07:36:15.54 さんくす sedやwcなどの外部コマンド?を使わない方法はありますか? 沸点が低いんだろうなぁ。 少しでもなにか言われたら、親を侮辱されたかのように感じるんだろうな なんとなく答える前に sedやwcなどの外部コマンド?を使わない方法はありますか? と書いても、同じようにキレていそうな気がするなw レスしただけでこの反応w 矛先をずらしているのもありがちだなぁw >>220-221 その _TAG("S.T.A.R.T") とかも字下げされてます echo ' _TAG("S.T.A.R.T")' なんかも考慮する必要はありません _TAG("S.T.A.R.T") は複数ありません ネストもありません >>222 可能ならman bashで出る内容だけで解決したいです。 _TAG("S.T.A.R.T")や_TAG("E.N.D")の前後にも行はあるので、わかりやすく _TAG("S.T.A.R.T")なんとか count=$((count + 1)) _TAG("E.N.D")かんとか ならベストなのですが。 >>253 while文で1行ずつ読んでSTART見つけたところからカウントしていってENDが見つかったら終了すりゃいいだけじゃないの 自分でどこまで作ったの? >>254 もういいから早くスクリプト作れって言ってんだよ >>255 なら今からman bash読むわ ちょっと量が多いから1週間待ってな 忘れるといかんからまたその頃に催促してくれ 自分で man 読んで自分で出来るようになる方が自分にとって有益だと思うんだが… awkでやればできるよ!・・・全部BEGIN これ萎えるw フレッシュなニンニクジュースを飲めばコロナの菌が死滅する この板の住民なら生ニンニクで腸内細菌死滅して病院送りになるのは知ってそう 言うほどUNIXやシェルスクリプトってコロナ菌に関係あるか? [ と [[ の違いなんかも理解できてないままflgやcontinueを使って書いてみました。 _TAG("S.T.A.R.T")の後でもループの度にflgをチェックするのが無駄なので _TAG("S.T.A.R.T")を探すループと_TAG("E.N.D")まで行数を数えるループを完全に分けてflgを無くしスッキリ出来たらいいのですが。 declare -i i=0 declare -i flg=0 for f in `cat $INPUT_FILE` do if [ $flg == 0 ]; then if [[ "$f" =~ \t*'_TAG("S.T.A.R.T")' ]]; then flg=1 else continue fi else if [[ "$f" =~ \t*'_TAG("E.N.D")' ]]; then echo 行数は $i exit 0 else i=$i+1 fi fi done >>264 > ループを完全に分けてflgを無くしスッキリ出来たらいいのですが。 まず for f in `cat $INPUT_FILE`を使うのはやめよう シェルスクリプトでテキストファイルを読むならwhile + read を使う そしてread は read してから read すると次の行を read する(当たり前だw) 一応それらしいのを書いてみました。 exitがあるのと、whileループの前と中にreadがあるのがちょっと不満です。 後チェックができるように do; read; while という使い方ができればいいのですが。 declare -i i=0 while : ; do read f <- 不要かも while [[ !("$f" =~ \t*'_TAG("S.T.A.R.T")') ]]; do read f done read f while [[ !("$f" =~ \t*'_TAG("E.N.D")') ]]; do i=$i+1 read f done echo 行数は $i exit done < $INPUT_FILE そもそも done < $INPUT_FILE とか書く必要ない script.sh < $INPUT_FILE とやればいいんだよ その方が柔軟性が高くなる そうすりゃスクリプトは中身だけで良くなる。endはいらない。 そして while read do にも置き換えられるやろ? read f <- 不要かも while [[ !("$f" =~ \t*'_TAG("S.T.A.R.T")') ]]; do read f done read f while [[ !("$f" =~ \t*'_TAG("E.N.D")') ]]; do i=$i+1 read f done echo 行数は $i 後出しっぽくてすみません。 $INPUT_FILE は_TAG("S.T.A.R.T")や_TAG("E.N.D")と同じく固定名なので汎用性は不要なんです。 それにこの部分はscriptの一部で本体には引数があるため毎回script.sh 引数 < $INPUT_FILE とやるのはちょっと... といって、このためだけに分割するのも... じゃあ { なかみ } < "$INPUT_FILE" とかすればいい $ eval "<" bash: 予期しないトークン `newline' 周辺に構文エラーがあります これってどういうこと? そりゃ < をbashに渡すから $ < と同じ結果になる訳で おふたりありがとう たしかに $ < と同じ結果になった でもnewlineというのはどこにも記述してないのにどうして `newline' なんだろう?と >>275 パーサーが入力の「末尾」も改行文字と同じに扱っている または入力末尾に改行文字を追加してからパースしている といったところじゃないかな あー、そういうことか、なるほどわかりました 日本語の中に突然newlineが出てきて、しかもわざわざクォートされてるからてっきり予約語かと思い込んでいた というか目に見えない予約語なんだろうけど ありがとうございます >>164 win鯖管か個人用途のみで使うなら7系はいいものだと思うけど、数百MB食うpwshがunix界隈で受け入れられるとはとても思えない まあ新興非b系シェルは駆逐されるかもしれんが そもそもまだMacとlinux主要ディストロにしか公式対応してないので IT職でなく、単にツールキットを享受できればいい人ならpwshでいいと思うよ たとえ趣味や仕事でも(だけど時代遅れな)b系シェルの技能は汎用性あるから、あえて普段から使うのも勉強になるよ あと怒涛の互換性ブチ壊しバージョンアップ中だから、せっかく書いても一年で動かなくなる まだソフトウェア開発には使えないのが現状 シェルスクリプトの特徴は「人間がそのまま読むことが出来る1行1データのテキストを扱う」という点なんだわ シェルスクリプトは分かりづらいからPerlやPythonを使うとか言ってるやつがいるけど 1行1データのテキストを扱うならば、シェルスクリプトが一番うまく処理できる 正確に言えば、シェルスクリプトだけじゃなくてUNIX系のCLIコマンドがそれを前提としたインターフェースになってる CLIコマンド=シェルスクリプトのAPIなんだよ pwshがunix界隈で受け入れられないのは、APIが全く違っていて互換性がないから API=CLIコマンドなので、プログラマの多くはAPIコマンドを知ってる シェルスクリプトがいつまでたってもPerlやPythonに置き換わらないのも それらの言語はCLIコマンドというAPIを使わないから CLIコマンドを使うならば、シェルスクリプトより簡潔に書ける言語が存在しない シェルなんだから外部コマンドは呼べるし、テキストも扱えるしそんなに変わらんのでは そんなに変らんということはすなわち、わざわざunix環境で使うモチベとしては弱いと思うが ドザーが流行りのwsl使うのには便利なんじゃね 昔ながらのwinコマンドは大体外部コマンドだけど、pwshはほとんど組み込みコマンドなのがなあ slsとか分けて提供してくれればbetter grep/findとして個人的には使いたいんだが >>283 Windowsのコマンドはスクリプトから使うことを考慮されてない物が多い 例えば、copyコマンドは、copyすると 1 個のファイルをコピーしました。 とか人間のためのメッセージが出てくるからテキスト処理に向かない バッチファイルは人間が操作するのと同じことただやるだけ (出力を加工しない)なのでバッチファイルから使う分にはそれでもいいが シェルスクリプトのように出力と入力をつないで処理することには向いていない だからpwshはWindowsのコマンドを呼び出さない 一方pwshで使うAPIは1行1データのテキストにはなってないし 普段使ってる外部コマンドではない どちらかと言えばPythonなどの関数に近い Unix/Linuxの外部コマンド・・・1行1データのAPIインターフェースでCLIからも参照する pwsh、Python、多くの言語・・・引数と戻り値のAPIインターフェースで言語内から参照しない APIのインターフェースが大きく違っていて Unix/Linuxの外部コマンドは改行の扱いが難しいなどの制限があるが その制限の範囲内ではスクリプトからも人間からも使いやすくて 他の言語には置き換えることが出来ないんだよ Windowsでシェルスクリプト動かそうとすると、パスの\のエスケープで気が狂いそうになるから その辺捨てたパワーシェルの割り切りは、それはそれで理解できるけどなー >>286 Windowsでシェルスクリプトって何を使ってるの? パスの\のエスケープなんかしたことないよ pwshはスクリプト言語としては悪くないと思うよ ただPythonなんかと同じようなプログラミング用の言語ということ Pythonにも当てはまるけどプログラミング用の言語は シェルスクリプトとはスタイルが異なる。 シェルスクリプトは端末操作に特化した言語だから プログラミングはしにくいが端末操作は得意 まあPowerShellでも普段からコマンドレット使って端末操作してます。 pwshでもコマンドレットをメインで使いますって人なら シェルスクリプトと同じような感じに見えるかもしれないけど そんな人いるのかな? >>287 Windowsはダブルクォートの直前にバックスラッシュがある場合のみエスケープとして扱うということに一応なってる。 しかし実はWindowsではダブルクォートも引数の区切りも解釈するのはアプリケーションの仕事なので実は上記のように解釈される保証はない。 >>288 アプリケーションの仕事って言うなら、 パワーシェルから呼び出したときも同じじゃん・・・ int main( int argc,char **argv){ printf("%s\n",argv[1]); return 0;} みたいなプログラムを書いて a.exe "abc xyz" みたいに実行しても処理系によって出力が "abc xyz" だったり abc xyz だったり "abc だったり…そんな時代もあったね。 SSDがいっぱいになってきたのでfindで各binを周りfileが吐いたリストをunstripped(だったか?)でgrep&stripするスクリプト書いた 半分くらいになるのなこれ… 今の所不具合は出てないからヨシ おすすめ >>287 ubuntuだけどbashからpwsh -cで便利なツールとして使うのがベスト 多少最適化されてそうなapt提供のプレコンパイル版でも60MiBあるから配布時依存に加えるのは厳しいのが悩み 私的ハックにはすごく重宝 >>286 `をエスケープに選んだのは英断だと思う m4と協調させようと思うと壊れるけど、まあm4のクオートは簡単に変えれるし満足 >>291 golang製のバイナリってstripすると壊れるんじゃなかったっけ >>294 マジかー!でも何がgoとか把握してない… 内蔵HDDの方はテラ余裕なのでそっくりコピーしてある、万が一あってもそっちからブート&コマンド全て使えるから問題起きてからでもいいかな… 学習コスト高そうだから何でも賢くキャストしてくれるキャスト器として使ってるわ [xml]'<foo>...'くらいのカジュアルユース 年だからjqとか付いてけないしjsonもキャストして.付けてるタブ補完連打でアクセス ただの型コレクションとして気兼ねなく使えばいい >>296 歳のせいにするな。お前の能力の問題だ。 噂のpwsh試してみたけど、とりあえずコマンドライン作業中の電卓代わりにはpythonよりはいいな 子シェルだからパス通ってて、普通に演算子と数学関数が下拵え無しで使えるってだけだけど 64KBと打つと65536を返してくるのは遊び心かな? まあスレ違いだねごめん 電卓代わりでbc/dc思い出して遊ぼうと思ったら今時のlinuxにはdcはいってないのね 頭の体操にいいのに残念 普通パッケージぐらいは用意されていて入れれば入るんじゃない? deb系なら apt-get install dc で使える for i in "予定1" "予定2" "予定3" do [ $i = "予定1" ] && echo "予定1"; sleep 3 [ $i = "予定2" ] && echo "予定2"; sleep 3 [ $i = "予定3" ] && echo "予定3"; sleep 3 done シェルスクリプトはperl にとって代わるCGIの記述言語って本当すか? >>305 そもそもCGIはすでに廃れてるって知ってる? 今どき本格的なサーバー側アプリをCGIで作るなんてないわけで まあ簡単なツールぐらいならやるかもしれんけどさ >>307 知らんのだがCGI以外でどう処理してるの?ジャバスクリプト? >>308 WebアプリケーションフレームワークがWebサーバ機能を持っていて、フロントエンドのWebサーバからリバースプロキシして使うのが多いかな。 だからWebサーバとアプリケーションの接続インターフェイスと言う感じじゃ無いんよ。 えっ、そうなの? perlじゃ無くCGIがオワコンで、マトモwebサービス作成にはもう使われ無いのね。 perl自体がオワコンかどうかの話は別として歴史の話をすると 初期はウェブサーバー+perlスクリプト、つまりCGIでウェブシステムが作られていた もう2000年とかその頃の話よ。とほほのなんとかとかKentなんとかとかが幅を利かせていた 当時のプロ(ホームページ制作会社)でもそういったCGIを使っていた時代 その後はPHPが登場したが、これはウェブサーバーにPHPをモジュールとして組み込む mod_phpが利用されていた。アクセスのたびにperlスクリプトを呼び出さないから速い 同じようにmod_perlというのもあった。 この頃のプロといえば自社でサーバーを保守管理するウェブサービス会社だったかな その後から現在はアプリ自身でウェブサーバーとして起動するようになった RailsとかPythonとかはそれが主。もちろんphpでもperlでもこの仕組が使える クラウドの時代のプロのシステムはほぼこれ。もちろん今もホームページ制作会社はあるけど ウェブサービス作ってる会社ってもうこんな感じじゃないでしょ? アプリにウェブサーバーが内蔵されてると言っても、それはアプリに最適化されていて 静的コンテンツを配信するのには適していないから >>309 のいうように前段に普通のウェブサーバー(nginxやapache)を配置して アプリ用のURLだけリバースプロキシでWebフレームワークにわたす仕組み シェルスクリプトは、ブラウザにモジュールとして組み込んだり シェルスクリプト自身をウェブサーバーにすることはできないからCGIオンリーで使うしか無い と思ったらmod_bashなんてあるのなw まあアクセス数が少ない個人用のシステムとか、特定のサーバーからアクセスしない 死活監視用のエンドポイント程度になら使っても良いんじゃね? 時系列はおかしいけども、仕組みとしては大体合ってるし、いいんじゃない? 間違ってると言うやつほど どこが間違っているかを言わない しかしこれは CGI が使われなくなったと言われれば違和感はある Web サーバーがリバースプロキシに変化してアプリが Web サーバーを持ったに過ぎないのだろう CGI とは Web サーバーから実行ファイルを走らせる技術だよね違うのかな >>316 アプリケーションにHTTPヘッダを環境変数で渡す方法などを定めたものがCGI、だからInterfaceなの。 この方法で渡していないならそれはCGIではない。 もともとリバースプロキシの機能はウェブサーバーにあったのだから どちらかと言えばウェブサーバーをリバースプロキシだけに使うように 使い方が変化してって言う方が適切だね ちなみに開発時だとウェブサーバーはあまり使わない ウェブサーバーとしての機能や性能は必要ないので アプリ内臓の簡易ウェブサーバー機能で十分だから >>316 > CGI とは Web サーバーから実行ファイルを走らせる技術だよね違うのかな 一番の違いはアプリが常駐しているかどうか CGIはアプリが常駐して無くてアクセスのたびにコマンドを実行する このコマンドを実行するっていうのはかなり重い処理なのでパフォーマンスが出ない 特にシェルスクリプトなんか外部のコマンドを組み合わせて処理するものだから 1アクセスでシェルスクリプト本体の実行の他に sedコマンド+grepコマンド+awkコマンド+jqコマンド・・・みたいになるから Perlで作るよりも確実にパフォーマンスが悪くなる。Perlよりも悪い選択 それに対してCGIじゃない仕組みはサーバーマシン起動時に1回コマンドを起動するだけ もし誰かに、これからのCGIはシェルスクリプト!シェルスクリプトでもこれだけの速度が出る!って 郵便番号から住所を検索するデモをみせてシェルスクリプトでシステム開発させようと洗脳する組織団体にそそのかされていたら それアクセスが多い時にパフォーマンス出ますか?他の言語とベンチマークして比較していいですか?って聞いたら良いよ 郵便番号のデータなんてたかだか十数MBしかないしSSD使ってりゃ0.01秒未満で読み込めるのは当たり前 そんな低負荷なデモを数回見せた程度でパフォーマンスの検証なんてできやしない >>319 fastcgiってcgiと呼んじゃダメなん? >>320 FastCGIはCGIの環境変数や標準入出力の内容をカプセル化してsocketで通信するように定められているから無関係ではないんだけど、 環境変数とか標準入出力を使っているわけじゃないからやはりCGIでは無いと思うよ。 そういやFastCGIなんて技術もあったな あれも「プロセス起動が遅い」という問題を プロセス終了をさせずにプロセスを使い回すことで 解決する技術なんだよな シェルスクリプトでそれがやれるかっつーと無理だろうな いやwikiによればhttps://ja.wikipedia.org/wiki/FastCGI 名前付きパイプもサポートしてるようだからから不可能じゃないのか? でもまあシェルスクリプトから呼び出すコマンドは どちらにしろプロセス起動になるわけで シェルスクリプトで全部実装するならまだしも 普通のシェルスクリプトではあまり効果がないだろうな 英語だし読む気はないけどなんかそういう技術があるみたいだw FastCGI shell script https://stackoverflow.com/questions/4685045/fastcgi-shell-script ここの Look at "Writing agents in sh: conversing through a pipe" まあ一般的にシェルスクリプトでFastCGIは無理(無意味)やでって書かれてるようだね んでさ>>305 に聞きたいんだけど > シェルスクリプトはperl にとって代わるCGIの記述言語って本当すか? ってどういう流れで誰に聞いたの? 二十年ぐらい前にコンピューターにちょっと詳しいだけの高校生や大学生の 会話で出てきた話だってのならわかるけどさ 今のウェブ開発ではCGIという単語自体でてこない >>324 年寄りと話すと、API叩くことをCGI呼び出すと表現するよ レガシーシステムの改修でもないかぎりCGIなんて出てこないし 新規でCGIとかいい出したら、そんな会社は切り捨てた方が良い PHP fpm ってよく使われてるように思うけど技術的には Fast CGI なんでしょ? 0埋めした2桁数字文字をdeclare -iの変数に入れると時々エラーになるので ぐぐったら0埋め数字は8進数扱いって、何か面倒だなぁ... 頭0は8進数ってC言語とか昔から使われてるけど 最近の言語は頭0を8進数とみなさないように変わってきてる気がするね 2桁とわかってるならdeclare -i i="${var#0}"でいけるよ そうでない場合はdeclare -i i="10#$var"でいけるかな bash以外だとダメかもしれんけど ありがとうございます。 expr でどうにか凌ぎました。 計算するときにコンソールで expr 以外に何か良い方法ありますか >>324 シェルスクリプトでCGIとかきくとユニケージを思い出すな あ、脱ケージだっけwww あれほど酷い開発手法はないと思うね >>342 いや、あれオモロいで。 ワンライナー繋げてwebアプリ。 小規模社内オフィス用に最適w 誰かPOSIX原理主義者とユニケージの関係教えてくれ どちらも秘密主義だからな。俺も少し興味があるが 非公開の独自技術には興味なくて裏で糸を引いているやつらに興味がある wikipediaを見る限りUSP研究所と金沢大学が手を組んでるっぽい USP研究所がユニケージという開発手法で怪しげなビジネスをしていて それにコネかなんかで金沢大学が手を貸して箔をつけてる感じ もしくは金沢大学関係者が作ったのがUSP研究所なのかもな POSIX原理主義者はUSP研究所もしくは金沢大学の関係者だと思われる 構成員の中の幹部クラスで多分3人ぐらいしかいない ただ引っかかるのはユニケージとPOSIX原理主義が矛盾しているという点 POSIX原理主義はPOSIXのコマンドだけを使うと言ってるがユニケージは独自コマンドを押し付けている ユニケージ=シェルスクリプト主義でそこから分岐したのが原理主義なのかもしれないな >>343 ネタとしてのオモロイだなw 東京ハンズで大規模対応でクラウドに移行して それに対応できなくなって今では闇とか負債と言われてるんだっけな https://www.hands-lab.com/tech/t5600/ ここにはBashのフレームワークってかいてあるな BashってことはやっぱりPOSIX原理主義とも違うな >>346 完全菜食と牛乳、卵は許すのような違いか。 ユニケージにベンダーロックインされて地獄を見るw 大規模化の可能性のある場合は、このネタシステムを使ってはいけないな。 POSIX原理主義者「シェルスクリプトは遅くない!なぜなら郵便番号から住所を検索なんで一瞬で探せる!」 ※CSVファイルは解凍した状態でたったの12MBです。 どんだけ小規模低負荷前提で吠えてるのかとw シェルスクリプトは連想配列が使えるから 原理的には高速 オーバーヘッドがない分 他の言語より早い場合が多いと思う 保守しにくいけど ファイルサイズに依存するオーバーヘッドはメモリ上に載せる部分じゃろ? 全部載せてしまえば定数時間のはずだけど、上限とかなかったっけ 載せないで逐次処理なら固定長レコード上に添字でジャンプのデータベースには勝てない 載せても多分勝てないけど 英辞郎くらいなら適当に整形してgrepで引いてるな、5秒くらいかかるが… 毎回読み込まず、&で起動して配列抱えたままsleep、named pipeをポーリングてもらうか 前から舐めるから時間かかってるだけだな、見出し語辞書引きなら既にソートされてるので人力二分探索が楽か イニシャルでファイルを8つくらいに分け、引数見て探すファイルを割り振るだけで十分一秒切れる >>350 >>352 問題はメモリ(連想配列)に載せた後 1件のデータを引いたら、そのまま終了してメモリを破棄するしかない つまり1件検索する毎に全データを連想配列に読み込むw >>354 普通にSQLiteでも使ったほうが良いのでは?w >>350 > シェルスクリプトは連想配列が使えるから原理的には高速 モダンな言語で連想配列使えない言語ってそんなにないと思うが POSIX準拠だと連想配列ないけどねw eval使えばそれっぽいことはできるけど >>353 一つのプログラムを常駐させ、もう一つのプログラムから問い合わせるってこと? それってシェルスクリプトだけで実現できるの? >>356 普段はdico(d)とかdict(d)使ってるよ、この用途には特化してる分sqlite3なんかより遥かに高速で優れてる ただ、自前の辞書に索引付けてdictのdbに変換…ってのは面倒なんだよ 英和の出来合いdbってdict.orgとかでも提供されてないしな テキスト形式の単一辞書(~100MB)をgrep、数秒のラグなら十分許容できるだろう 取り敢えず事足りればいいんだよって思想です >>359 デーモンなんかの実装は大体そうでしょ mkfifoでファイルのように読み書きできるパイプ作れるでしょ? 無限whileループの中で1秒程度sleep、パイプに書き込まれてるかreadでチェック(所謂原始的なポーリング) 追伸>>361 プロセスの関係について答えてなかった クライエントがコマンドライン引数を単にnamed pipeへ書き込むだけのシェルスクリプトでいいです というか必須でないです ぶっちゃけやることはecho query >fifo それを$eiji queryと書けると分かりやすいというだけですね 老婆心かもしれないけど、常駐シェルスクリプトなんて何ら特別なものでないよ 常駐しないシェルスクリプト=exitの記述が存在している、あるいはeofに達するもの 常駐できるシェルスクリプト=signalやらで殺さなければexit/eofに達しないモノです shを常用するやつは居るが 流石にed常用するやつは居らんな edは生の改行文字食わせる必要あるし、sedのように;で区切れないから、コマンドラインから使いにくい… printf %s\\n cmd1 cmd2 ...をeasyedとか名付けておけば、easyed cmd1 cmd2 ...で使いやすくなるね ただ、sedやawkでカウンタ設定して何行後の処理を指定するような処理を書いている事に気づいたら、そういう処理はedの領分 前後の相対アドレスを+nのように簡潔に指定できる あと、diffがedのコードを吐けるというのもあって、それをテンプレにして弄るとバッチ的な処理はより早く書けると思う >>362 問題はデーモン側じゃないよ。 起動するのも、named pipeに書き込むのもそれはできる 問題は、その後どうやって情報を受け取るのか?って話 もっと具体的に言えば、POSIX準拠だと シェルスクリプトは双方向パイプを使えない >>354 > イニシャルでファイルを8つくらいに分け、引数見て探すファイルを割り振るだけで十分一秒切れる 前方一致検索ならそれでもいいと思うけど、中間一致や全文検索だと結局すべてのファイルをgrepしないといけない SQLiteなら全文検索もあるようだ http://ytyaru.hatena (ドット)com/entry/2017/07/19/000000 >>360 > ただ、自前の辞書に索引付けてdictのdbに変換…ってのは面倒なんだよ インデックスつけるのが面倒なんでしょ? SQLiteならテーブル作ってデータを入れていくだけだよ >>370 原理主義者周辺にはNoSQLってこだわりがある。 使えるならnamed pipeが行儀良いと思うけど、ポーリングさせるならただのファイルでも環境変数でも何でもいいんでね あんまりSSDへ頻繁に書き込みたくないなら環境変数か 個人コマンドラインツールで一秒で返ってくれば問題ないという要件なら、ファイル分割で必要十分だろ メモリも今時100MBくらい一時占めるのは有りだとしても、常駐させるとなるとチリツモ >>374 いや、ファイルや環境変数を使うというのはどうでも良くて それらをどう使って実現するのか?って話だよ。 あなた、自動運転を実現するにはどうしたら良いか?って言う話に AIを使えばできるんです。みたいなことしか言ってないよw > 個人コマンドラインツールで一秒で返ってくれば問題ないという要件なら 個人用途であれば、その程度でも構わないってことには反論はしないけどね C10K問題(クライアント1万台問題)が発生するような場合には、それじゃ使い物にならないけど >>376 もしかして 1. コマンド実行 2. 特定のディレクトリにファイルを作る 3. デーモンが1秒おきにそのディレクトリを監視している 4. デーモンはファイルを見つけたら処理をして新しく結果ファイルを作る 5. 1のコマンドは結果ファイルができるまで待ってて見つけたらその内容を表示する って話? ・パイプで繋ぐと早い。 ・標準入力を<でリダイレクトするより、パイプを通じてcatで流し込んだ方が早い。 経典に書いてあるw 一つのnamed pipeに複数プロセスから同時に書き込んでも データは混ざらないんだっけ? デーモンがメモリにデータを蓄えておくって 原理主義者的にはどうなんだろう?w >>378 おれはそう解釈するけど 結果もクエリも数行だろうから、環境変数の方がいい 標準sleepは1s単位なので微妙に要件満たせないけど、適当な代替コマンド用意できないなら2秒になってしまうが… msec sleep便利よ サーバスクリプトは$queryを1s sleepしながらループしてチェック、空で無ければクリアして検索に入り、$responseに書き出す 検索時間をa-zの26ファイルに分けて検索時間を1/26~0.1s程度にまで削減、コードも頭文字とファイル名に整合が取れて短くなるだろう フォアグラウンドのクライアント側は$query設定して1s sleep、(既に設定されているはずの)$responseを標準出力へ書き出す 完了フラグ立てるとか面倒な事やるのはシェルスクリプトの領分超えてると思うわ $responseが空ならエラー吐いて落とす 何回か走らせてみて、時間は適宜調整で決め打ちが楽だろう >>385 > 結果もクエリも数行だろうから、環境変数の方がいい いやいや環境変数は子プロセスには伝搬するけど デーモンとコマンドのように親子関係にないでは やり取りできないんだよ > サーバスクリプトは$queryを1s sleepしながらループしてチェック、空で無ければクリアして検索に入り、$responseに書き出す なんつーかシェル変数(環境変数)をグローバル変数とでも勘違いしてるような書き方だな サーバースクリプトが$responseに書き出しても それは他のプロセスからは見えないんだよ > 検索時間をa-zの26ファイルに分けて検索時間を1/26~0.1s程度にまで削減、コードも頭文字とファイル名に整合が取れて短くなるだろう それだと中間一致には対応できない >>389 たしかに クライエントから起動するわけじゃないから、コマンド置換やsourceも使えないし、PID把握して/proc以下のfdに書き込む必要あるのか readするって言ってる>>361 の方が多分俺より賢いな 面倒だからやっぱ一時ファイルで… 直接の親にならdeclareの拡張や文字列evalシェル関数で書き換えられるけど、兄弟の環境は変える手段無いのか 兄弟でもメインループの中でexport hoge=hageをファイルに書き出して互いにsourceすれば共有できるぞ 結局一時ファイル作ることになるから、それを許容するなら全部一時ファイルでやり取りするか、 それを嫌うならpsでPID特定して直接リダイレクト シェルスクリプトでTCPとかUDPとかどうです旦那 シェルスクリプトから離れてごめんだけど、dicodはちゃんとした辞書形式(索引-シーク位置)にコンパイルしなくても受け付けてくれたはずだよ、dictは使ってないので分からん emacsの何とか形式ってやつがマニュアルに記載あったはず、単なる見出し+テキストのプレーンテキスト マニュアルが激しく読みにくいけどsedあたりで頑張ってみたら まあ索引付けないならgrepより速くなる保証もないわけだけど 曖昧検索や部分一致、逆引き、履歴等々色々高度な事もできるので、例え遅くてもやる価値はあるかと これね https://puszcza.gnu.org.ua/software/dico/manual/dico.html#outline PDICクライアントは 見出し セパーレータ テキスト(改行等エスケープ) セパレータ 関連語等のメタデータ でエクスポートできたはずなので、sed等でセパレータ後にタグ前置、次いでセパレータを改行に置換すれば大体おんなじ構造 下の方見るとpythonの辞書(ハッシュ実装)も受け付けるようなので、もしパフォーマンスに不満があれば次に試すと良さそう あー descriptionとinfoタグは辞書についてのもので、項目はヘッダと本文のみ、メタデータは対応してないか まあ本文に含めてしまって、逆引きで代替できると思う… >>391 > PID把握して/proc以下のfdに書き込む必要あるのか え?そんなことできるんか? /proc以下のファイルは調べることが出来るわけで そんなこと出来たら不正なデータをインジェクションできてしまう気がするんだが あー、でもprocが必要だからmacOSじゃ無理? あ、勘違いっぽい。こんな感じで1〜10の頭に>をつけて出力させてる間に seq 10 | { echo $BASHPID; while read a; do echo "> $a"; sleep 5; done; } 他の端末から echo aaa > /proc/<PID>/fd/1 ってやったら 確かに 1〜10 の間に出力が割り込まれたけど頭に>はついていなかった >>398 プラットフォームによって違うと思うけど、ubuntuなら/proc/PID/fd/0|1|2、何だったかのunixではstdin|out|errが各プロセスのfile descriptorへのシムリンクになってるはず(/dev以下、/tmpとか) 自分の起動したプロセスなら当然rw権限はある、無ければそもそも入出力できないよ システムに関わるデーモンなんかはroot権限で走ってるはずなので、セキュリティ的に問題は起きない 連投ごめん。標準入力のファイルディスクリプタは0だった んで、すこし変えてこんなふうにして実行してみたんだけど for i in $(seq 10); do sleep 5; echo "$i"; done | { echo $BASHPID; while read a; do echo "> $a"; sleep 5; done; } 本当に他端末から出力の間に割り込ませられたよ・・・ seq 10 してるから 10 個の数字が出力されると思いきや それ以上の適当な文字を出力させられる。 これセキュリティ的に大丈夫なん? うーん、自分しか読み書きできないから大丈夫・・・なのか? それにしてもコマンドの出力結果の間に出力を割り込ませられるとはwww echo helloでコンソールに文字が出るのも、キーボードから入力できるのも、ファイルをディスクに書き出すのも、シェルが暗黙のうちにそのデバイスファイル群を繋ぎ合わせてる結果 なんら特別な事じゃないよ proc使えば別プロセスの環境変数も読み込める・・・と思ったら起動時の環境変数か。 ってことは別プロセスから新たに子プロセスを起動すれば まあいろいろできそうだけど、どっちみちprocが必要なんだよな >>405 それはそうだけどproc=カーネルがあるプロセスの情報を 他のプロセスに公開してるからできることだよね? macOSとかはprocがないから、内部的にはデバイスファイル郡を つなぎ合わせていたとしてもそれが他のプロセスからは見れないはず いずれにしろPOSIX標準ではなさそう そもそもカーネルやシステム中核プロセスが不可視であるべき、ってのは常識なのか? ディレクトリの閲覧権限はxとwで制限できるから、そりゃ隠れてるのも居るかもしれないけどさ Macは使わないので分からんが、windowsだってタスクマネージャ開けばユーザー権限で干渉不可なシステムプロセスがゾロゾロ動いてるの見えるけど OpenBSDでは5.7からprocfsは削除された https://www.openbsd.org/plus57.html > Deleted procfs (always suffered from race conditions and is now unused). procfsを削除しました(常に競合状態に悩まされ、現在は使用されていません) UNIXの全てがファイルという考えは面白かったが 本当に全てがファイルであるというは正しい考えなのだろうか? 読み書き出来るならファイルと見做せるんじゃね 環境変数なんかは読み書きできるけどファイルじゃないね cpuは一応procにcpuinfoあるけど、別にフルアクセスできるわけじゃなし形だけね lsofやpsで情報が得られるが、lsでアクセスできないならファイルとして抽象化されていない、でいいのかな(procfsが無いならlsできない、でいいの?) それならOSのレベルで抽象化しなくても、シェルのレベルでファイルシステムのように見せる事もできる windowsがそうだ) cmdの振る舞いを見るとOSレベルでの一貫性は皆無だけど、pwshからはプロセス、レジストリ、環境変数まで全部ファイルシステムとして読み書きできるわけで > (procfsが無いならlsできない、でいいの?) 無理やりlsで表示させるんじゃなくて 別の形のコマンドを作るべきじゃなかったのか?ということ >>408 race conditionって具体的に何だろ、デバイスファイルに読み書き競合、あるいは排他制御でブロッキング頻発か event pollみたいな仕組みはlinux固有だっけ? どう上手くやろうがfdのやりくりをする方式はスケーラブルじゃないと思ってる 多重I/Oでパフォーマンス向上とか言ってOSに過剰なfd要求コール送り続けてるんだから >>412 たぶん情報を取得したが取得中にリアルタイムで情報が変わってしまい 矛盾した情報になってしまったとかじゃね? もしくは複数のファイルから取得した情報が矛盾してしまうとか 情報を取得してからそれを利用するまでの間に時間があるから 取得した情報が信用できないというのは当然として少なくとも取得した時点では それらの情報は矛盾しないようにスナップショットである必要がある 例えば歯抜け連番名ファイルを詰めて連番にする場合 for f in renban* ; do mv $f 新ファイル名 done とやると、該当ファイルが0個でもループ内の mv を実行しようとしてエラーになります。 ループ前に該当ファイルの有無のチェックが不要な方法はないでしょうか? >>412 懐しいw pollがSVRで、BSDがselectってやつかな?w Linuxは両方使えたが、少くとも昔のLinuxカーネルでは実装はほぼ同じだったけどな… >>414 たぶんrenban*がfに入るってるよね モダンなシェルならsetで好きな挙動選べるよ (bashならnullglobとかglobfailとか) ただ、わざわざその一文の為にオプションいじくるよりは普通にチェックした方がいいと思うよ たまにおまじない書き忘れて頭ひねったりするから こんな感じかなあ? set -- renban* [ $# -eq 1 ] && [ ! -e "$1" ] && set -- for f in "$@"; do mv $f 新ファイル名 done でもまあ、ファイル名一覧を取得してからmvしてる間に ファイルが別プロセスによって消されてリすることがあるから どちらにしろmvがエラーになる可能性はあるんだよね ls renban* | while read f;do mv $f 新ファイル名; done だとループには入らないけど、ファイルがないときにlsがエラー吐くねw find -maxdepth 1 -name "*.csv" | while read f;mv $f 新ファイル名;done これでどう?w > ファイルが別プロセスによって消されてリすることがあるから ↑もちろんこの問題は避けられないけどね。 どうせワンタイムだろうしあんまり細かいこと気にしてるとハゲるぞー といいつつ もしrenbanが何万にものぼるとして、globしてからmvに取り掛かるまでの時間差が気になるんだったら findに-name 'renban*'を処理させ、アクションの逐次実行を指定する;を渡せば隙は(ほぼ)ないはず -exec {} target$suffix \; +を渡すと速いけどバッチ処理だからglobとおんなじ >>419 find -maxdepth 1 -name "renban*" -exec mv {} 新ファイル名 \; かw そうだね、それが正解だw (なんでもパイプで渡してしまう悪いくせを晒してしまった…w) >>418 スルーしてほしいってのが要望のようだけど、対象指定をミスったなら失敗する方が健全だと思います >>421 まあ、依頼主の要望を可能な限り叶えたまでさ。 あとは好みと状況でどちらでもお好きな方をw ただ、この場合lsでやっつけてるけど、本当はlsの出力はそんなにあてにして いいものではないので、気をつけて。 いろんな意味でfind -execの方が正統だよ。 shのglobはソート済みが保証されてたと思うけど、findはどうだったか自信がない… 誰か試せる人補足よろしく ソートしてから逐次実行してるんなら期待してたアトミック性は無いねー >>423 findはディスクに忠実にファイルシステム上の順番だね。 そして、globは確かにソートされてるようだ。 ちなみにlsもソートされるし、それはオプションで変えられる、と。 一応、環境書いとくと、Fedora33のbashにて >>425 ありがとう 探索ツールである性質上もしやと思ったらやっぱりそうか じゃあglob+ソートかlsだね 危なかった 414です 回答ありがとうございます。 ループ前チェックは何だか美しくないように思えたので(個人の感想です) 0個なら即doneに移る方法はないものかとお尋ねした次第です。 0個でも一度はループに入るという仕様が続いているのはきっと何か意味があるのでしょうね。 ループじゃなくて*の展開の仕様だよ 合理的に考えれば、展開を指示してマッチ無しならば0件にヒットしたとして何も返さないか空文字 展開が失敗したと考えてエラーのどちらかだろう 多分深い意味はないから気にすんな いや気にしなきゃだめか ココがヘンだよbshくらいの気持ちで構えてれば、案外可愛く思えてくるぞ >>419 > どうせワンタイムだろうしあんまり細かいこと気にしてるとハゲるぞー うっせーハゲ! lsとglobがソートされるってどこに書いてあったっけ? 前に見た気がするけど英語の中から探すのめんどいw globで見つからなかった時、検索した文字列を返すのは おそらく安全側に倒したからだと思ってるんだがいい例が思いつかないな 例えばcmd renban* hoge.tar.gzだったら普通は引数が2個以上になると思うが 見つからない時cmd hoge.tar.gzとなって危険とか もしくはエラーメッセージをわかりやすく出すのが目的だったりするのかな? 空ディレクトリでls renban*を実行した時 「renban*」という文字列を返せば、エラーメッセージは分かりやすい > ls: 'renban*' にアクセスできません: そのようなファイルやディレクトリはありません 空文字を返せば、エラーメッセージは分かりにくい > ls: '' にアクセスできません: そのようなファイルやディレクトリはありません 何も返さなければ、何も表示せず正常終了 ・・・あ、これかw 空ディレクトリでない(file1 file2 file3というファイルが有る)場合renban*が 何も返さないとlsが実行されるからfile1 file2 file3と表示されるんだ renbanなんたらを処理しようとしてるのに、関係ないファイルを処理してしまう。 一つでもあればループ内を実行して、(それ以上)無ければ抜ける。 だから、(最初から)無ければそのまま抜けて欲しいな、と。 該当するものが無いのだからループ内を実行するのは無意味だし。 標準出力の速度を制限したり、通信速度を表示するコマンドを探しています。どなたか知りませんか? >>435 pvコマンド(Pipe Viewer)でどうよ sed の 's/foo/bar/' スラッシュ直前の【s】って何の意味でしょうか? g:global i:ignore のような意味ありますか? またman以外でこのような略語を調べるサイトなどありますでしょうか? >>438 substituteのs info sedより > 3.3 The s Command > The s command (as in substitute) is (略) edコマンドで気になってるのはv versed subst? でもversedって多分古語だしなあ… exec grep -v "$@"にvrepと名付けることにした >>441 grep の -v は --invert-match だから inVert substitute じゃねーの? _数字列_数字列_数字列_を含む文字列から先頭の数字列だけを取り出したいので 前段階としてそれより前の部分を切り出すために echo ${文字列%_*[0-9]_*[0-9]_*[0-9]_*} としてみたのですが、 aaa_bbb_ccc_ddd_eee_123_4_567_xxxxx_123yyy_4f6_789c_zzz の場合には aaa_bbb_ccc_ddd_eee ではなく aaa_bbb_ccc_ddd_eee_123 になってしまいます。 どうすればいいでしょうか? >>443 シェルの変数置換じゃなくて、sedで置換したほうがええやろ。 まっとうな正規表現が使えるしな。 彼はsubstringの概念がないんでしょうかね。 任意個数の数字だけの塊をglobは表現できないので、お題の変換は無理 >>443 こんな感じでいけるんでね?前段階の話すっ飛ばして答えだけど テストしてないので動かなくても知らん isnum() { case "$1" in *[!0-9]*) return 1 ;; *) return 0 ;; esac } str="aaa_bbb_ccc_ddd_eee_123_4_567_xxxxx_123yyy_4f6_789c_zzz" IFS="_" set -- $str while [ "$#" -gt 0 ]; do if isnum "$1" && isnum "$2" && isnum "$3"; then echo "$1" fi shift done >>445 のいうように、sedで一行それも大したことない正規表現で済むな シェルスクリプトだけという課題の制限でもなければ シェルスクリプトで無理といった途端 シェルスクリプトの実装が出てきたんで 慌てて取り繕ったか?w ねじ曲がりすぎ そんな発想になるのは、お前>>450 ぽいな 俺は面白いと思うぞ、やりたくないけどな bashやzshならパターンの否定が使えるextglobオプション+%パラメータ展開を使うのが多分一番楽かと 引数を表示するのに echo $1 だけのスクリプトファイルを作って実行するのですが なぜか引数が1&2等の場合にうまくいきません 標準出力とエラー出力を引数にしたいってことループしないそれ 単に sh scriptfile.sh 1&2 ってやってしまってるだけじゃないの 呼び出す側の問題 echoで展開後に&が問題になることはないのでクォートしなくても問題にはならない。クォートした方がいいけど >>460 クォートしろ。 sh scriptfile.sh "1&2" >>462 マウントマウントうざ。 >>456 には「わかりきったこと」ではないのに。 間違った指摘してたくせにw 何で常時偉そうにしなきゃならんのだかだが、自覚ないアホか コマンド展開で質問。 echo $(...) | sed ... みたいなスクリプトで、$(...)内のコマンドが失敗したとき、そこでエラー終了してほしいんだけど、ムリ? set -eしても、これには効果がないもよう。 >コマンド置換ではムリだねえ コマンドの引数にあるのはね コマンド置換でも変数に入れるだけなら終了ステータス返る/見れる=-eなら止まる。そっちはやってるとかあるだろうけど、いちおう え?馬鹿なの? var=$(...) echo "$var" | sed ... ってするだけじゃん 流れとか関係なくどこまで知っているのか想定もせず、 偉ぶれると思ったら食いつくいつもの馬鹿だろな 口は悪いけどみんなと仲良くしたいだけなんです大目に見てあげてください >>470 おまえこそ、いつものマウンターマウンターだな。w >>466 ,467 どーも。 やっぱそうか。。。 -o substfailとかあってもいいのに。 >>467 > そっちはやってる うん、書かなかったけど、やってはみてた。 でもやめた。 なんかひっかかるし、いずれ誤って直しそうだし。 declare/set/exportで書いたら失敗が無視されることも気になる。 だからさ、もう結論出てるんだよ var=$(...) echo "$var" | sed ... こう書けば終わり sedのホールドスペースは、その内容を削除するにはどうすれば? とりあえずs/.//g;xでできたけど、もっと直接的なやりかたはないんかなー、と。 怪しげなシェル芸が宣伝中 【広告記事】今、ユニケージ開発手法にギークが熱狂するワケ【USP研究所代表&オープンソースOSコミッター対談】 ttps://type.jp/et/feature/14070/ 空白行でいくつかのブロックに分割されたテキストにて、 文字列にマッチするブロックを出力する方法を探してます たとえば 111 222 222 aaa 222 333 333 333 のようなテキスト中から、aaaを検索した際に、その前後の空白行に囲まれたブロックである 222 222 aaa 222 という結果を得たいです いまは最初にブロックごとに一時ファイルを作り、それぞれに対してgrepにて検索し マッチしたファイルを出力、としているのですがブロックが20万ほどあり、 分割も検索も遅くて困ってます 該当するブロックは3〜5個程度なので、むしろgrepでマッチする行番号を調べる →テキストをless等でひらき該当行へジャンプ →そのブロックをコピペ の方が早いくらいでして Linux板くだ質スレでいい加減嫌われたから流れてきたって感じかな > ブロックが20万ほどあり この時点でデータ構造の方を考え直すべき \n\n(\n...)ではない \nをスペース(やタブなど)に | grep '\<aaa\>' | スペース(やタブなどにしたの)を\nに テキトーに色々 $ for i in {1..2000000}; do echo aaaa; echo bbbb; echo cccc; echo $i; echo dddd; echo eeee; echo ffff; echo gggg; echo; done > aaa $ time (awk 'function keepp () { if (matched) { for (i=0 ; i < nkeeps ; i++) print keeps[i]; print } matched=0; nkeeps=0 } NF == 0 { keepp(); next } { keeps[nkeeps++]=$0; if ($1 == "1414213") matched=1 } END{ keepp() }' < aaa ) real 0m10.556s user 0m10.281s sys 0m0.271s $ time (awk 'NF == 0 { print; next } { printf "%s ", $0 }' < aaa | grep '\<1414213\>' | tr ' ' '\n') real 0m11.101s user 0m1.177s sys 0m12.259s $ time (tr '\n' ' ' < aaa | sed -e 's/ /\ /g' | grep '\<1414213\>' | tr ' ' '\n') real 0m2.344s user 0m1.452s sys 0m0.814s $ time (tr '\n' ' ' < aaa | sed -e 's/ */\ /g' | grep '\<1414213\>' | tr ' ' '\n') real 0m3.678s user 0m1.484s sys 0m1.078s $ time sh smf1.sh real 0m4.088s user 0m2.324s sys 0m3.803s $ cat smf1.sh #!/bin/sh SMF=/tmp/xxx [ ! -x $SMF ] && { cc -x c - -o $SMF << 'EOS' #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { const size_t BUFFER_SIZE = 1024 * 1024 + 1; char *buffer = (char *)malloc(BUFFER_SIZE); while (fgets(buffer, BUFFER_SIZE, stdin) != NULL) { char *ep = buffer + strlen(buffer) - 1; if (ep >= buffer && *ep == '\n') *ep = '\0'; if (buffer[0] == '\0') putc('\n', stdout); else printf("%s ", buffer); } return 0; } EOS [ $? -ne 0 ] && exit 1; } $SMF < aaa | grep '\<1414213\>' | tr ' ' '\n' $ time sh smf2.sh real 0m0.717s user 0m0.381s sys 0m0.436s #!/bin/sh SMF=/tmp/xxx [ ! -x $SMF ] && { cc -x c - -o $SMF << 'EOS' #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { const size_t BUFFER_SIZE = 1024 * 1024; char *srcbuff = (char *)malloc(BUFFER_SIZE); char *dstbuff = (char *)malloc(BUFFER_SIZE+1); char *const de = dstbuff + BUFFER_SIZE - 1; int numLFs = 0; size_t len; while ((len = fread(srcbuff, 1, BUFFER_SIZE, stdin)) > 0) { char *sp = srcbuff; char *const sep = sp + len - 1; char *dp = dstbuff; char c; while (sp <= sep) { if ((c = *(sp++)) == '\n') numLFs++; else{ if (numLFs > 1) *(dp++) = '\n'; else if (numLFs == 1) *(dp++) = ' '; numLFs = 0; *(dp++) = c; } } fwrite(dstbuff, 1, (size_t)(dp - dstbuff), stdout); } return 0; } EOS [ $? -ne 0 ] && exit 1; } $SMF < aaa | grep '\<1414213\>' | tr ' ' '\n' 481です いろいろな方法について情報ありがとうございます 参考にさせていただき、取り入れていこうと思います 特定の文字列で始まるファイルが存在するかの判断はどうすればいいでしょうか ぐぐって見つけた ls を使う方法 if ls $f* > /dev/null 2>&1 then echo $f で始まるファイルがあります fi だと該当ファイルが存在しない場合に ...にアクセスできません: そのようなファイルやディレクトリはありません というエラーメッセージが表示されます。 また、 for g in $f* ; do echo $f で始まるファイル $g があります done だと該当ファイルがない場合でもループの中に入ってしまいます。 >>489 zshでじゃないの そういう余計なオプション(nomatch)がデフォでオンになってるのでオフにする setopt nonomatch >>489 あと、forの場合は、シェルが対象がなくてglob展開できない場合はglobそのままの値となる。forの場合に限らずglobはそういうもの for g in $f* の場合は、g が $f* になるので、展開されずにそのままなのかチェックするのは必要 for g in $f*; do [ "$g" = "$f*" ] && { echo 展開できませんでした; break; } な感じで >forの場合に限らずglobはそういうもの なので、 if [ "$(echo $f*)" != "$f*" ] then echo $f で始まるファイルがあります fi とかとも書ける zshでnomatchだと余計なメッセージが出るし、>>489 のls使ってる方が見た目なにしたいのかわかりやすいと思うけど、いちおう >>492 ああ、念のためには元globとの比較ではなくて -e する方がいいな [ "$g" = "$f*" ] でなくて [ -e "$g" ] zshネタ、シェルスクリプトではなくて zsh script になってしまうが null_glob ってのもあるんだな setopt null_glob ってすると、エラーメッセージは出ないわ、globに当てはまらない場合globを入れない/消すわで、>>489 のどっちも動くようになるな そんな応えは求めてないだろうけどw ああ、bashにもnullglobって同じようなのがあるのか シェルスクリプトという汎用ではなく各シェル固有独特の機能なので使わないだろけど そして、bashにも failglob ってあるのか。オンになってたら>>489 はbashでも似たような動きになるか bashはデフォではオンではないので、zshだろと思うけど 489です ありがとうございます。 とても参考になりました。 コマンドの出力を(だけ)ではなく、シェルそのものの出力(=コマンドの出力もになる)を消すなら if (exec 1>/dev/null;exec 2>&1;ls $f*); then echo $f で始まるファイルがあります fi て現在のシェル環境を変更(元に戻すのが面倒なのでサブシェルでそこの環境を変更)で消すというのもできたな >if (exec 1>/dev/null;exec 2>&1;ls $f*); then execのディスクリプタ操作は羅列ができるようなのね if (exec 1>/dev/null 2>&1;ls $f*); then の方が良さげか >>489 check() { set -- "$1"* [ -e "$1" ] } 最短だとこうかな? set -- "$1"* でシェルのglob展開を用いて位置パラメーターにセットする ファイルが見つかった場合、そのファイル名が$1に入る ファイルが見つからなかった場合、"$1"*という文字列が入る まずありえないとは思うけど"$1*"という名前にアスタリスクが含まれた ファイルがある可能性を考えると>>492 よりも-eでチェックした方が良い と>>494 で書いてあったかw >>493 > >>489 のls使ってる方が見た目なにしたいのかわかりやすいと思うけど ls $f* は意味がない。シェルのglob展開されてからlsを実行してる。 つまりls file1 file2 file3 のようなものを実行してるだけ。 呼び出す前にすでにファイル一覧を取得してる 単に呼び出しコストが高い[ -e ] になってる 見た目っ言ってるだろ そんなコスト気にする必要もないから、見た目とそっちの方を重視してだよ 他人の提案を直接ダメ出しして自分の知識自慢をしたがり、 マウント取るのが目的なやつは他のシェルスクリプトスレでも居るけど、 同じやつかな lsの見た目の何がいいの? ファイルリストを取得しても何やってるのか意味わからんでしょ >>503 > 同じやつかな 違うけど、お前が知識不足でマウント取られたやつだってのはよくわかったよw lsはファイルがあるか確認するのに普通に使ってるだろ、手打ちで >>505 見た目って言ってる裏を読めないで決めつけられてもな 同じやつとしか思えないその短絡的なレス でたw 自分が説明できてないだけなのに 裏が読めてないと相手のせいにする 詐欺師の手段と同じ 自分にある意味ダメ出しされたらイキリマ来るくせに。変なやつ 説明できないとか似たようなフレーズはあいつもすぐにしてたなあ 巣に帰れよw 「裏を読めない」と言った時点で 自分で書いてないって言ってるのってわかってないのかな? 思い込み激しすぎるんだよな 例のPOSIX原理主義者みたいだw 読めませんでしたと素直に言えよ わざわざ見た目って言ってるのはなんなのかは、細かいこと言うなら、 また、そこまで食い下がるならそれぐらい裏読めよ せめて、読めませんでしたと素直になれよ。他人にダメ出しばっかしてないで 自分にダメ出しされたらイキリまくるくせに、他人にダメ出しはするって、 マジでマウント取るのが目的でしかないだろう マウント取るためだから素直には人の言うことは読めないから、 イキリまくることになるんだろうなと そのしつこさはやはりなっていう マウント取るためだからしつこく食い下がるんだろうなあ... 書いてないものは読めません って短絡的に言えちゃうのは確かにアホだな、それが攻撃的な人格のヤツがなら >>513 自らアホ晒してるだけだぞ なんでPOSIX原理主義者に結びつけるのか意味わからん もちろんあんな自ら手足縛るのは嫌いだ/必要ないし、イキってる姿勢はもっと嫌いだし ホント短絡的だな。トンチンカンな決めつけばかりって何したいんだか >>515 > なんでPOSIX原理主義者に結びつけるのか意味わからん そりゃPOSIX原理主義者に知識不足でマウント取られた恨みがあるから、というぐらいは読めるよねえ >>518 イミフすぎな文で、読めないぞ 誰がPOSIX原理主義者なの? 裏読めないやつがPOSIX原理主義者ってことになる文だと思うけど、その文は POSIX原理主義者って出てきたのは、>>510 だぞ >>510 がPOSIX原理主義者?>>510 のレスの相手であろう俺がPOSIX原理主義者?? 俺がPOSIX原理主義者だとしたいなら、 POSIX原理主義者のくせに知識不足でマウント取られた恨みがあるから かな だとしてもPOSIX原理主義者に結びつける説明にはなってないなあ カオスだな。ここまでにしとこか >>520 × POSIX原理主義者 ○ 例のPOSIX原理主義者 シェルスクリプトスレでは、意味が全然変わる。w >>520 510には「POSIX原理主義者」に知識不足でマウント取られた過去があって 恨みがあるから「POSIX原理主義者」という言葉を持ち出した ってことでしょ 510がマウントとられてぐぬぬとなった時に、510には相手がPOSIX原理主義者のように思えたらしいというだけで 本当にPOSIX原理主義者かどうかさえ不明だし、誰がPOSIX原理主義者かなんてどうでもいい fishについて質問です fish_vi_key_bindingsを入力するとviモードに入りプロンプトの左にモードステイタスが表示されますが、 $XDG_CONFIG_HOME/fish/config.fish にfish_vi_key_bindingsを記入した場合はログイン後すぐにviモードか使えますがモードステイタスが表示されません どうやったら表示出来ますか? を、$XDG_CONFIG_HOME/fish/config.fish に書いてるんじゃないの >>529 どうもありがとうございます それらは書かれていませんが、こう書かれてありましたのでコメントアウトしてみたらモードが表示されるようになりました function hybrid_bindings --description "Vi-style bindings that inherit emacs-style bindings in all modes" for mode in insert default visual fish_default_key_bindings -M $mode end fish_vi_key_bindings --no-erase end set -g fish_key_bindings hybrid_bindings インサートモードの時にjjを押したらノーマルモードに戻りたくてfish_user_key_bindingsに以下のように書いたらまたモードが消えました function fish_user_key_bindings fish_vi_key_bindings bind -M insert -m default jj backward-char force-repaint end 端末では正常な $declare -i w0=180 w1=30 w2=20 w3=50 ; w3=w3+(w0-w1)/10-1 ; echo $w3 ですが、shファイルで使うとなぜかエラーになります。(w? の数値は違います) 予期しないトークン `(' 周辺に構文エラーがあります w3=w3+(w0-w1)/10-1 ですが、分割すると通ります。 w2=(w0-w1)/10 ; w3=w3+w2-1 理由をご存知でしたら教えて下さい。 GNU bash, バージョン 5.0.17(1) >>532 理由はよく分からないけど extglob が on ならエラーにならないね なんかbashの仕様のグダグダなところを踏んだって感じだな。 エスケープされていない生の ( は基本的にwordの途中に出てこないので、 w3+( ときたところでsyntax errorになる。 ところが、shopt -s extglob しておくと、 +(hoge|fuga) みたいなパターンマッチを許すため、 w3+( をエラー扱いできなくなり、全部まとめて数式としてパースしてくれる。 *( も可。しかし、/( と -( は不可。 おとなしく $(( )) を使っておくのが吉。 自分が理解できないからって bashのせいにするのは恥ずかしい行為 grepとかで使える正規表現の「\s」は、manページのどこに書いてますか? 「\b」「\w」は、man 1 grepに書いてあるけど、「\s」は見当たらない。 declare -i n; n="3/2" は通るのに、n="1.5" が通らないのはなぜだろ エラーで出ている通り、 リテラルもintegerしかでintegerでは.(5) というのは数値はあり得ない 数値の一部ではないので算術演算子とみるが、算術演算子としてもそんなのない てとこかな リテラル じゃなく、右辺中 か >>537 manには無さげかな。manには無いがPOSIXのドキュメントには詳しくある ああ、決まり事を規定する団体が規定してるドキュメントでは ユニコードコンソーシアム のがある https://unicode.org/reports/tr18/ これを実装していればだが >>540-542 やっぱり記載漏れかな? 理想としては、man 7 regexくらいに全仕様がまとまっててほしいんだけどな。 個人的には、慣れで「\d」を使ってしまって、よく標準コマンド系でガッカリするんだよね。。。 >>543 他の環境は知らんがGNUのなら仕様はinfoを読めというスタンスだぞ >>544 たしかにinfo grepには「\s」が書いてあるな。 でもinfo bashには書かれてなくて、man 3 regexに回されてるような。 結局はinfoでも解決しなさそうな気がするんだけど、違う? info regexだとlibc関数のことが表示されるし、たとえばman 7 regexに相当するinfoは存在しないんでは? まあ、man7セクションに入るような内容はGNUに関係なさそうだとは思う。 シェルスクリプトの [ -a (AND) と -o (OR) ] は非推奨だかんね https://qiita.com/ko1nksm/items/6201b2ce47f4d6126521 には -a や -o ではなく && と || を使うように書かれています。 否定の場合、 [ $a != $b ] と [ ! $a = $b ] はどちらを使ってもいいのでしょうか? >>547 いいんじゃね? ただ [ "$a" != "$b" ] や [ ! "$a" = "$b" ] ってしないとだめだけど あと ! [ "$a" = "$b" ] でもよさそう 昔のFreeBSDでは [ -n abc -lt 5 ] みたいのが通った記憶 [ gnu 8.30で今試すとextra argument '[' と怒られる 手元のunix magazineコレクション(1997-2000)にもこの用法が述べられてるが、まあ要らん機能だわな シェルスクリプトって息が長いから そういう使うべきじゃないものも残っていて困るね さすがに古すぎる機能は互換性切り捨てた方が良くない? whileの、条件が偽でも一度はループって仕様が不思議 そんな仕様なんて無いし シェルスクリプトに文句言ってるやつの8割は 自分の知らない言語を勉強せずに文句言ってるだけなんだなってわかる do while をシェルスクリプトでどう実現するかって話もWeb上であるけど、 それなんの話ってことになるわな ぐぐっても見つけられないんだけど functionの中のlocal変数に整数属性付与って出来ないのかな? bashの話だとして普通に整数属性付いてるぞ? bash -c 'v=1+2; foo() { local v; declare -i v; v=3+4; echo $v; }; foo; echo $v' 7 1+2 というかdeclareで-gをつけない限り デフォルトでlocalになるだろ? >>556 ありがとうございます。 declare はスクリプトファイルの先頭でしか使ったことがなかったのでループ内(や関数)でも使えるとは知りませんでした。 なるほど、それならデフォルトlocalですね。 >>557 使い方の例を見て学ぶタイプなので^^ 3つの引数を必要とする関数があります。 x=$1 y=$2 ANS=$3の絶対値 $3が正の場合はxを、負の場合はyを増減し、xとyとで算出される結果がANSになった時のxまたはyを返します。 x=a[0] y=a[1]とし、最初に$3の符号で添字を0または1に設定することでループ内での場合分けを減らしたいと思います。 質問:整数配列の宣言はできますか? >>558 内部的にはlocalとかreadonlyとか変数に属性つけるやつは 内部的にはdeclareかtypesetの別名 >>559 昨日、近所の吉野家行ったんです。吉野家。 そしたらなんか人がめちゃくちゃいっぱいで座れないんです。 で、よく見たらなんか垂れ幕下がってて、150円引き、とか書いてあるんです。 もうね、アホかと。馬鹿かと。 お前らな、150円引き如きで普段来てない吉野家に来てんじゃねーよ、ボケが。 150円だよ、150円。 なんか親子連れとかもいるし。一家4人で吉野家か。おめでてーな。 よーしパパ特盛頼んじゃうぞー、とか言ってるの。もう見てらんない。 お前らな、150円やるからその席空けろと。 吉野家ってのはな、もっと殺伐としてるべきなんだよ。 Uの字テーブルの向かいに座った奴といつ喧嘩が始まってもおかしくない、 刺すか刺されるか、そんな雰囲気がいいんじゃねーか。女子供は、すっこんでろ。 で、やっと座れたかと思ったら、隣の奴が、大盛つゆだくで、とか言ってるんです。 そこでまたぶち切れですよ。 あのな、つゆだくなんてきょうび流行んねーんだよ。ボケが。 得意げな顔して何が、つゆだくで、だ。 お前は本当につゆだくを食いたいのかと問いたい。問い詰めたい。小1時間問い詰めたい。 お前、つゆだくって言いたいだけちゃうんかと。 吉野家通の俺から言わせてもらえば今、吉野家通の間での最新流行はやっぱり、 ねぎだく、これだね。 大盛りねぎだくギョク。これが通の頼み方。 ねぎだくってのはねぎが多めに入ってる。そん代わり肉が少なめ。これ。 で、それに大盛りギョク(玉子)。これ最強。 しかしこれを頼むと次から店員にマークされるという危険も伴う、諸刃の剣。 素人にはお薦め出来ない。 まあお前らド素人は、牛鮭定食でも食ってなさいってこった。 答え:できまsん ありがとうございます。 色々やってみたら、配列として宣言しなくても使えるようです。 declare -i i a[0] a[1] ; a[0]=3 ; a[1]=6 ; i=1 ; a[$i]=${a[$i]}+1 ; echo a=${a[$i]} a=7 ちょっとスレチかもですが、 for filename in * とかでカレントディレクトリにあるファイル名を得る場合、どんな順番なのでしょうか? ディレクトリエントリ順とか、ファイル名順とか。 ある程度ファイルがあるところで echo * すればわかる >>563 GLOB POSIXに規定されてる The glob() function shall store the number of matched pathnames into pglob->gl_pathc and a pointer to a list of pointers to pathnames into pglob->gl_pathv. The pathnames shall be in sort order as defined by the current setting of the LC_COLLATE category 名前順 >>566 ,563 SORTしないというオプションもあるが、その場合には順番の決まりなんてないということになるね >>568 > □お約束 > ・特記なき場合はBourne Shell(/bin/sh)もしくはPOSIX準拠の互換シェルがデフォルトです。 POSIX準拠が当たり前、 POSIXにはない/POSIXで足らない勝手に拡張部分で独自が当たり前 って当たり前がわからないんだろな 拡張するにしてもPOSIXをベース+αって馬鹿でもわかりそうなもんだが 機能的に必要最低限のPOSIXを無視する利益なんてないだろに POSIXを無視する利益は互換性でしょ? 今までの動きを変えたらだめ >POSIXを無視する利益は互換性 www >今までの動きを変えたらだめ 前段からそれになるとか無茶苦茶 POSIXの経緯、POSIXは何をベースに作られたか勉強してきてから寝言言うんだよ 皆様ありがとうございました。シェルはbashです。 名前順的に最後のファイル名を得るには for filename in * ; do : done とするしかないようですね。 でもKDEのDolphineの自然なソート(ゼロパディング分の0を無視)のようなオプションは欲しいかも >>573 > 名前順的に最後のファイル名を得るには 普通に ls -r | head -1 でよくね? >>572 何をベースにってBSDベースでしょ? SolarisとかはSystemVベースだからtrコマンドの挙動が違う 互換性を重視してPOSIXを無視してる >>572 おら。ちゃんとPOSIXの経緯調べてきたか? 黙ってないでなんとかいえや >>573 sh ではできるだけパイプで処理することを考えるんだ もちろん for, while などが必要な局面はあるが パイプで済むなら速くて簡潔でフィルターとして組み合わせられる >>578 ファイル名に改行が入る場合はどうすればいいのでしょうか? 自分ならまずそういうアホなファイル名を変更するが 権限がなければまあ find -print0 | xargs -0 くらいだな >>580 POSIX準拠じゃないので FreeBSDで動きませんw POSIX準拠じゃなくてもFreeBSDで動くけどな POSIXにないのでも、ツール間で合わせ合う、どっちかがどっちかに似せるというのは普通にあるしな POSIXにないオプションは使用禁止だ そんなものを使うと持続性がなくなる なんらかの理由で別のOSに変更になった時 システムは動かなくなってデータはただのゴミになる 何度言えば理解できるのか はいはい、原理主義ごくろうさん 使ってる本人次第でしかないのに押し付けとかホント原理主義者は 原理主義者は自惚れてるけど無知さがだだ漏れる 無知さを隠す誤魔化すためのマウント取りでしかない リッチー大佐はC言語も使える ただし分割コンパイルやmakeといった高度な機能は使わない そんなものはなくてもシェルスクリプトでmake.shを作れば良いからだ >>581 pkg install findutils それ入れなくてもFreeBSDのfindで可能だけどな がっつりGNU依存のにしても、それ入れる+ちょっとパス修正だけだわな BSDのfindなら find 場所 -print0 | xargs -0 持続性なら、もはやPOSIXよりも、Linuxのほうがいいのでは。 bashの関数で文字列を返したい場合、その関数名を文字列名称に使うことは仕様的に可能ですか? function kotae () { kotae=$1$2 } kotae ab cd echo $kotae >>593 関数と変数の名前空間は別なので別に構わない、そして宣言(declare)してなければ変数concはグローバル ややこしいのでそういう使い方のおすすめはしない concはkotaeの間違い 頭の中で勝手に命名しちゃった >>593 そのようなことをしたい場合はこうする function kotae () { printf -v $1 "%s" $2$3 } kotae ret ab cd echo $ret bash 5.2.2(1)で最初の!だけ全角の echo "abc!? xyz!" は通るのに、半角にすると echo "abcecho "abc!? xyz!" > になってしまいます。 一対の"で通すにはどうすればいいのでしょうか? >>594-596 ありがとうございます。 printfのvオプションは初めて知りました。 ヒストリ機能 知らない/活用してないならオフにしておくべき 対話モードでしか機能しないから切っても特に問題はない 恥を忍んで質問させて下さい: Larry Wallせんせーが書いたmetaconfigが普及せずに、同じ機能を果たす、 Autoconf/Autotoolsが普及した理由って何でしょう? 1)Perlよりm4の方が普及してた(どっちも文法はアレだけど) 2)というかPerl嫌いな人が少なくなかった 3)そのほか(開発モデルとか) ...imakeって何だっけ? Autoconf/AutotoolsはGNUだからじゃね?しらんけど rsync -avR -e ssh ... rsync -avR -e ssh ... このように6行以上書くとエラーになるんですがどうしてでしょう? ssh: connect to host xxxx: Connection refused rsync: connection unexpectedly closed (0 bytes received so far) [sender] rsync error: unexplained error (code 255) at io.c(228) [sender=3.2.3] >>602 クライアントからの接続要求の処理中に次の接続要求が来たら待たせるようになっててそのバッファが5個だからそれ以上に次々と接続要求きたらConnection refusedを返すようになってる 少し時間を空ければ大丈夫なはず てか、サーバーは何? >>604 ありがとうございます。そうでしたか。 コマンドの内容と関係無さそうだったので迷いました。 接続先のサーバーは自宅のraspiです。 もしかしてファイル転送を多重化しようとしてるのかな そういうオプションがあったような気がするけどね rsync はい、ぶたがみーるー まあ、ここにも俺がいるわけですけどねw function YesNo { local yn while true; do read -p " [Yes/No" "$1" "]: " yn case $yn in [Yy]*) return 0 ;; [Nn]*) return 1 ;; [Ee]*) if [ ! "$1" = "" ]; then return 2; fi ;; esac done } #main YesNo ":いいえ /Else:その他" echo $? exit 実行すると、read: `:いいえ /Else:その他': 有効な識別子ではありません とエラーになるのですが、どうすればいいでしょうか? -p に渡っているのは " [Yes/No" だけで、残りの "$1" と "]: " は yn と同じく変数名として解釈されている read -p " [Yes/No $1 ]: " yn read.cgi ver 08.0u [upliftProject] - 2023/07/09 Walang Kapalit ★ | uplift ★ 5ちゃんねる