シェルスクリプト総合 その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/ まず添削してくださいってどうしてほしいんだ ちゃんと動いてんならそれはもう正解だと思うんだが >>167 ちゃんと動いているかどうか判断できないから聞いてるんでは エラるのはbashのバージョンのせいかな?3.2.57ではエラる/4.3.48では問題ない だとしたらPOSIX utils云々はちょっと違うんじゃねと思わなくもない。POSIX utils云々って書いている意図がよくわからんけど case文をこうしたら3.2.57で動いた case $i in (*1?) echo th;; (*1) echo st;; (*2) echo nd;; (*3) echo rd;; (*) echo th;; esac おおっ。ぱーふぇくつ(?)やねっ! ( が必要??なんなんなん??と謎だけど $() 内では、case の ) を case の ) と認識してないで、$( の終わりと見てまうってのか。それで普通は使わない ( をか。いちおう ( はつけてもいいのね。つけてもつけなくてもいい存在みたいだけど え…… >>164 のやつ、GNU bash 4.4.12,zsh 5.3.1,dash全てで動いたんだけど(Debian GNU/Linux)。 もちろん$()判定の不具合を回避したcase ()版でも動いたけれども。 bashの前のバージョン 3.2.57 でのなんですけど あ。>>170 でそう書いてあるな……。すいません。 sedなどで 1. 「%」以降改行までを削除 2. ただし「%」の直前に「\」があれば削除しない (要するにTeXシステムのコメント除去) をしたいです。また、できればなのですがPOSIXの範疇で行いたいです。 しかし2.を表わす正規表現が分かりません。教えていただけないでしょうか。 sedでsed -e '/%/{}'のようにして{}の内部で「\」が前置されているか判定するのが一番一般的かとは思うのですが それさえ……。 どうかよろしくおねがいします。 sed -e '/^%/d' -e 's/\([^\]\)%.*$/\1/g' でも確かTeXってオプション引数に%含まれてる場合コメントにならないんじゃなかったか? \somecs[hoge=42%]{VAL} ↑こういうの。いや俺の記憶違いかもしれんが sedのスレもあれば 正規表現のスレもある なんでここで聞く 以下のCのソースコードをシェルスクリプトに直したいのですが難しくてできない状態です お願いできますでしょうか? Cでは動作確認済みです インデントするとここに貼れなかったので、見にくくなっていてすみません どなたかよろしくお願いします #include <stdio.h> int main(void){ int res, i; printf("2以上の整数をキーボードから入力してください。\n"); scanf("%d", &res); for (i = 2; i <= res; i++) { if (i == res) { printf("%dは素数でした。\n", res); } else if ((res % i) == 0) { printf("%dは素数ではありません。%dで割り切れます。\n", res, i); break; } } return 0; } 判定方法から見直した方がいいんじゃないの なんか無駄そう 以下のCのソースコードをシェルスクリプトに直したいのですが × 難しくてできない状態です ○ 馬鹿だからできないです 勝手に難しい状態にするんじゃねーよ 普通に読めば自分にとっては難しいってことなんじゃ 大学生の宿題も困るが読解力の無いバカも困る プライドで自分が馬鹿でわかりませんって言うことができないから それは悪くねぇけどさぁ、難しい状態になっちゃんてんのよー って言いたいからそう書いてるんだろ それぐらい読み取れよ よほど気に障ったか気に入られたらしいwどっちかな? >>194 わざわざまた出てくるとかどんだけプライド高いんだよ w >>202 拗らせるだけだからもう触んな。わかるやつにはわかってるから Cからawkだとつまらない解になってしまうな。 awk '{for(i=2;i<=$0;i++){ if(i==$0){print $0"は素数でした 。"} else if(($0%i)==0){print $0"は素数ではありません。"i"で割り切れます。";break; }}}' <<< "$(read -p "2以上の整数をキーボードから入力してください。" res ; cat <<< "$res")" >>205 いい加減にしろ。うざいって言われてるのはお前だってわかってないのか? curl -s "http://hage.com.json" ; | jq -r '.main | .detail_list[] | .file_list[] | .date, .file_title, .file_name' これだと、date と file_title とfile_name の内容が表示されるんですが、 detail_listと同じ階層にあるnavi_nameの内容も表示させたい場合はどう書けばいいですか? よろしくお願いします。 >>209 とくにこだわりがないのであれば jq じゃなく parsrj 使えば? aaa=(888 犬 `date +"%Y%m%d"010000 -d last-sunday`) bbb=(777 猫 `date +"%Y%m%d"150000 -d last-Saturday`) ccc=(666 鳥 `date +"%Y%m%d"000000 -d last-friday`) for hoge in "$aaa" "$bbb" "$ccc" do if [ -e ~/${hoge[1]}_${hoge[2]:0:4}_${hoge[2]:4:2}_${hoge[2]:6:2}.mp4 ]; then exit 0 else ffmpeg -i ~/output/${hoge[2]}-${hoge[0]}.aac ~/${hoge[1]}_${hoge[2]:0:4}_${hoge[2]:4:2}_${hoge[2]:6:2}.mp4 fi done こんな感じのスクリプト書いたのですが、配列が展開してくれません。 どうすれば変数に入れた配列が機能するでしょうか アドバイスお願いします。 >>210 jqにこだわりはないが、 parsrjなんて誰も使ってないものは使いたくないなw >>189 状態ってなんだよwwwって話だよなあ 頭の悪い人は理解できないみたいだけど やりたいこと想像してベタにやってみたけど printf "%s %s %s\n" ${aaa[@]} ${bbb[@]} ${ccc[@]} | while read hoge0 hoge1 hoge2; do if [ -e ~/${hoge1}_${hoge2:0:4}_${hoge2:4:2}_${hoge2:6:2}.mp4 ]; then exit 0 else ffmpeg -nostdin -i ~/output/${hoge2}-${hoge0}.aac ~/${hoge1}_${hoge2:0:4}_${hoge2:4:2}_${hoge2:6:2}.mp4 fi done ...て、ほぼ配列じゃなくなっちゃったは >>217 あとは、そのbash依存の文字列の〜文字目をとってくるってのをなくそう っていうかdate使って%Y_%m_%dとかでいいだろと よくいる偉そうにしたいのが主な目的なのがわいてる感じ そういう言葉でしか言い返せないのな 悔しかったら技術で勝負しろ どこに勝負要素があるのか分からない しかし最近汚いコードがばらっと貼り付けられまくるのは同一人物なのか? 身に覚えがなかったら勝負とか言わないよなあ。てか、勝負ってw なにか偉そうにしたい/マウントとりたいのがありありだな >>221 違うんじゃね。汚いとか言いだしたらきりがないぞな。言うなら整形して上げたほうが意味あるんじゃね 年月日を配列でw printf "%s %s %s\n" ${aaa[@]} ${bbb[@]} ${ccc[@]} | while read hoge0 hoge1 hoge2; do fuga=(`echo $hoge2 | sed 's/^\(....\)\(..\)\(..\).*/\1 \2 \3/'`) if [ -e ~/${hoge1}_${fuga[0]}_${fuga[1]}_${fuga[2]}.mp4 ]; then exit 0 else ffmpeg -nostdin -i ~/output/${hoge2}-${hoge0}.aac ~/${hoge1}_${fuga[0]}_${fuga[1]}_${fuga[2]}.mp4 fi done からの〜 printf "%s %s %s\n" ${aaa[@]} ${bbb[@]} ${ccc[@]} | while read hoge0 hoge1 hoge2; do set - `echo ${hoge2} | sed 's/^\(....\)\(..\)\(..\).*/\1 \2 \3/'` if [ -e ~/${hoge1}_$1_$2_$3.mp4 ]; then exit 0 else ffmpeg -nostdin -i ~/output/${hoge2}-${hoge0}.aac ~/${hoge1}_$1_$2_$3.mp4 fi done 元のソースが汚いと修正も面倒だなとw まず一旦ループと変数をやめる if [ -e ~/犬_2018_06_06.mp4 ]; then exit 0 else ffmpeg -i ~/output/20180603010000-888.aac ~/犬_2018_06_06.mp4 fi if [ -e ~/猫_2018_06_06.mp4 ]; then exit 0 else ffmpeg -i ~/output/20180603150000-777.aac ~/猫_2018_06_06.mp4.mp4 fi if [ -e ~/鳥_2018_06_06.mp4 ]; then exit 0 else ffmpeg -i ~/output/20180603010000-666.aac ~/鳥_2018_06_06.mp4.mp4 fi つぎに、変数に入れ直す そして書き込もうとしたらNGワードとか言われたから ついでに関数にする infile=~/output/20180603010000-888.aac outfile=~/犬_2018_06_06.mp4 output "$infile" "$outfile" infile=~/output/20180603150000-777.aac outfile=~/猫_2018_06_06.mp4 output "$infile" "$outfile" infile=~/output/20180603010000-666.aac outfile=~/鳥_2018_06_06.mp4 output "$infile" "$outfile" output() { $infile=$1 $outfile=$2 if [ -e "$outfile" ]; then exit 0 else ffmpeg -i "$infile" "$outfile" fi } 一旦余計な変数を排除する output ~/output/20180603010000-888.aac ~/犬_2018_06_06.mp4 output ~/output/20180603150000-777.aac ~/猫_2018_06_06.mp4 output ~/output/20180603010000-666.aac ~/鳥_2018_06_06.mp4 output() { [ -e "$2" ] && exit 0 ffmpeg -i "$1" "$2" } >元のソースが汚いと修正も面倒だなとw だろ?w そこはスルーでええやん、別に求められているわけでもないんだし まあ、お疲れ様です(嫌味ではない) 日付の部分を元に戻す output "$(date +"%Y%m%d010000" -d last-sunday)-888.aac" "犬_$(date +"%Y_%m_%d" -d last-sunday).mp4" output "$(date +"%Y%m%d150000" -d last-saturday)-777.aac" "猫_$(date +"%Y_%m_%d" -d last-saturday).mp4" output "$(date +"%Y%m%d000000" -d last-friday)-666.aac" "鳥_$(date +"%Y_%m_%d" -d last-friday).mp4" output() { [ -e "$HOME/$2" ] && exit 0 ffmpeg -i "$HOME/output/$1" "$HOME/$2" } くだらん文字列結合を省く output "$(date +"%Y%m%d010000-888.aac" -d last-sunday)" "$(date +"犬_%Y_%m_%d.mp4" -d last-sunday)" output "$(date +"%Y%m%d150000-777.aac" -d last-saturday)" "$(date +"猫_%Y_%m_%d.mp4" -d last-saturday)" output "$(date +"%Y%m%d000000-666.aac" -d last-friday)" "$(date +"鳥_%Y_%m_%d.mp4" -d last-friday)" output() { [ -e "$HOME/$2" ] && exit 0 ffmpeg -i "$HOME/output/$1" "$HOME/$2" } 最終的にこんな感じかな(適当にやったので途中のコードはバグありだろう) output "%Y%m%d010000-888.aac" "犬_%Y_%m_%d.mp4" last-sunday output "%Y%m%d150000-777.aac" "猫_%Y_%m_%d.mp4" last-saturday output "%Y%m%d000000-666.aac" "鳥_%Y_%m_%d.mp4" last-friday output() { infile=$(date +"$1" -d "$3") outfile=$(date +"$2" -d "$3") [ -e "$HOME/$outfile" ] && exit 0 ffmpeg -i "$HOME/output/$infile" "$HOME/$outfile" } もっとやりたいならoutput関数を以下のような仕様の引数の関数ににしてもいいし output 010000 888 犬 last-sunday output 150000 777 猫 last-saturday output 000000 666 鳥 last-friday 順番変えてこうすりゃ最初の配列と同じようになる output 888 犬 010000 last-sunday output 777 猫 150000 last-saturday output 666 鳥 000000 last-friday まあ、配列なんかいらんっちゅー話だ >>230 > なんかだらだらって感じ だからいったろ? 元のコードが汚いと修正が面倒だって そうだな。やるつもりはなかったが、 例えば関数を作りたくなければ、こんな感じで行けるぞってことぐらいかな while read -r a b c d; do infile=$(適当に修正しろ) outfile=$(適当に修正しろ) [ -e "$HOME/$outfile" ] && exit 0 ffmpeg -i "$HOME/output/$infile" "$HOME/$outfile" done <<DATA 888 犬 010000 last-sunday 777 猫 150000 last-saturday 666 鳥 000000 last-friday DATA こういう場合は標準入力として受け取ってループで回せってことだな >>234 型なんて文字列しかねーよ HTMLのフォームからのPOSTと同じだ 白状する 181からここまで貼られてるソースコード全く読んでない 読む気起きない 別に構わんよ。きたねーコードだなって 直感的に思って、それを治すことで 俺の直感は正しいことを証明して 自分で納得してるだけだから 自分が汚いコード書いてた(誰でもそうだろう)&そこから綺麗にすることを学んだとこってとこかな もうちょっと経験つんだらそんな誰でもそうだったとこなんてスルーだろうな。綺麗にすることには際限がない/突き詰めれば&極論では個人の好みに帰結するってとこで、そんな初心者的なのにいちいち文句を言うのが低レベル的なw >>238 a=1 echo $((a + 1)) この場合の$aは数値じゃないんですか? >>212 for hoge in "$aaa" "$bbb" "$ccc" "$aaa" "$bbb" "$ccc"は、最初のアイテムを示すだけ(888, 777, 666)で間違い "${aaa[@]"が正しいもしくはとしたかったのだろうが、だったらforの機能的にも変数をArrayにする必要はないだろう。その記述以下でなんかするのでないなら aaa/bbb/cccは単なる文字列として、for内で必要となったらArrayに分解すれば簡単に目的は達成するだろう (てか、配列にするならaaa/bbb/cccなんて個々の変数じゃなくてそれこそそれを配列にすればいいのにと思うけど) aaa="888 犬 `date +"%Y%m%d"010000 -d last-sunday`" ... for fuga in "$aaa" "$bbb" "$ccc" do hoge=$($fuga) if [ -e ~/${hoge[1]}_${hoge[2]:0:4}_${hoge[2]:4:2}_${hoge[2]:6:2}.mp4 ]; then ... >>247 必要となったら数値とみなす/数値に変換するだけだろう a=hoge の場合は、hogeは数値に変換できないからしょうがないので0にしてまうし、 [ a -eq 0 ] なんて場合は、数値に変換できないのでエラーになるし。逆にa=1とかでエラーにならないのは数値だからと思えそうだが、単に数値に変換できてエラーにならないだけだろう あくまでも文字列でしかないのは、 a=1 a="1" a='1' のどれも同じってとこからもそう推察できそうな。そもそも明らかな文字列でさえa=hogeだったりするけど >>248 >"${aaa[@]"が正しいもしくは } 閉じ忘れ。てか、"${aaa[@]}"でも間違いで、"${aaa[*]}" だな >>248 >"${aaa[@]"が正しいもしくは } 閉じ忘れ。てか、"${aaa[@]}"でも間違いで、"${aaa[*]}" の方だった >>234 >>238>>249 以前にこちらのスレでお世話になった者で横からですが勉強になります >>248 ありがとうございます。 実は他の方のレスを見て、関数というものを調べて ある程度スッキリしたコードにできたのですが 当初自分の頭で考えていた>>212 のようなコードがが動くようにご指摘いただけたのは 非常に助かりました。ありがとうございます。 質問です。bashの配列を他のbashスクリプトに コマンドライン経由でわたすにはどうしたら良いのでしょうか? Arrayひとつを単一の文字列で渡して、受けたとった方がArrayに戻すかなあ sub-script.sh "${array1[*]}" "${array2[*]}" "${array3[*]}" ... sub-script.sh: array1=($1) array2=($2) array3=($3) Arrayのアイテムの内容がIFSに引っかかってたらIFSを書き換える(/同調)するかなあ。よくありそうなアイテムがスペースありとかだったら、アイテムの内容として入ってなさそうなタブにするとか (IFS=$'\t'; sub-script.sh "${array1[*]}" "${array2[*]}" "${array3[*]}" ...) sub-script.sh: array1=($1) array2=($2) array3=($3) (分解時のセパレータとしてはタブもデフォルトIFSに入っているので分解時には特に設定する必要はない) てか、そんなに配列をばんばん使わない方がいいんじゃねと思わなくもないw >>255 コマンドライン経由の意味はよくわからないが、 多分ファイルを使うのがいいと思う。 [渡す側] declare | grep "渡したい変数" > /path/save [受け取る側] source /path/save そのままでできると思う方が全くわかってないなという。まあ全くわかってないんだろうけど >>255 xmlなりjsonなり独自形式なりで渡せよ 言語のオブジェクト(配列)を他のプロセスにそのまんま渡せるスクリプト言語ってなんかあったっけ? 間にはシリアラズ/デシリアライズなどの仕組みがあるのは当然だが、そんなの全く意識させない言語でサポートしている言語って。フレームワークなど使えばは抜きで。スクリプト言語でなくてもいいけどとりあえずこのスレなのでスクリプト言語で >>257 あ、 >分解時のセパレータとしてはタブもデフォルトIFSに入っているので分解時には特に設定する必要はない 何言ってんだか。せっかくスペースをセパレータとされるのを避けているのに、設定しなきゃダメだろう sub-script.sh: ORIGINAL_IFS="$IFS" IFS=$'\t' array1=($1) array2=($2) array3=($3) IFS="$ORIGINAL_IFS" >>265 じぇーそんとかそういうためにあるんじゃないの? ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.4 2024/05/19 Walang Kapalit ★ | Donguri System Team 5ちゃんねる