シェルスクリプト総合 その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/ $ cat a.file > b.file とやるのと $ cp a.file b.file とやるので違いが生じる場合はありますか? >>120 b.fileというディレクトリがあった場合の動作 >>123 によると cat a.file > b.file/ ってやるといいんだって 意図してディレクトリじゃないからつけろもなんもないのにな Linuxのは実装はしてるみたいだな。デフォではないから話の流れでの実装してるとは言えんけど シェルスクリプトの勉強をするのにおすすめの本はありますか? お知恵お借りしたいです。 awk '($3 !~ /ここにパイプ区切りで記述したい/) && ($4 ~ /01/)' output.txt 上記のawkで条件に当てはまるファイルを絞り込みたいのですが その1 別ファイルからのawkの結果を $aaa に設定してある その2 $aaa は複数列の出力なので set コマンドにて位置パラメータに分けてある その3 各変数を展開して文字列としてパイプで区切ってawkを使いたい。 以上のようなことをやってみたのですがどうもうまく行きません。 また、違うやり方もあるようでしたらご教示いただけるとありがたいです。 よろしくお願いします。 > $aaa は複数列の出力なので set コマンドにて位置パラメータに分けてある これはどういう意味? set はシェル自身の設定だと思うんだけども cat ZZZ.txt |grep XXX hoge fuga と複数行でしたので aaa=$(cat ZZZ.txt |grep XXX) としてみました。 そして set $aaa と設定して $1 $2 $3 ...と変数が自動で割り振られるなら増減しても対応できるのでは考えました。 (本来は0個のときもあるのでそれも考慮しなければならないんですが) そして $1 等に入っている変数(hogeやfuga) を展開してパイプで区切れれば動くと思うんです。 ごめん俺の理解が悪いと思うのだがあなたのやりたいことが見えない。 他の人にまかせるわ。 もしくはZZZ.txtの内容をプライバシーに障らない程度に具体的に教えてほしい。 「ZZZ.txtからgrepで取り出した値をパイプで連結して処理する」という文言からは ZZZ.txtには命令が一行ずつ書かれているように受け取れるのだが、そうじゃないよね。 それとも「パイプで繋ぐ」というのはシェルのパイプ実行ではなく単に文字列としてパイプを区切りとして使うという意味? もしそうなら $ cat ZZZ.txt | grep XXX | tr '\n' '|' | sed 's/|$//1' ↑こういうので行けるけど。違うでしょ? 説明がヘタですみません。ZZZ.txtの中身はyoutube等の URL タイトル 日付 がタブ区切りで複数行書かれているファイルです。 123.com hoge 02 456.com fuga 05 789.com peke 08 のような感じです。 それらから条件から当てはまる行や列を抜き出してパイプ区切りにしたいのです。 パイプの解釈は hoge|fuga で hoge or fuga と展開して awkのパターン入れて読ませたい訳です。 >>137 なるほどね。こういうこと? (ZZZ.txtの代わりにヒアドキュメント使ってる) $ cat <<. | awk '($2 ~ /(hoge|fuga)/) && ($3 ~ /02/) {print}' example111.com hoge 02 example222.com hoge 03 456.com fuga 05 456example.com fuga 02 789.com peke 08 . example111.com hoge 02 456example.com fuga 02 勉強不足でヒアドキュメントの知識が浅くて申し訳ないのですが 多分合ってると思います。 うまくいかないのは hoge|fuga の部分が一定でなく peke|hoge|miso だったり fuga のみだったりするので悩ましいのです。 条件をコマンドの結果から作りたい&その条件をawkの条件に埋め込みたいってだけ? hogehuga=( $(cat ZZZ.txt |grep XXX) ) SAVEIFS=$IFS IFS=$'|' hogehuga="${hogehuga[*]}" IFS=$SAVEIFS [ "$hogehuga" = "" ] && hogehuga="0個の条件" awk '($3 !~ /'"$hogehuga"'/) && ($4 ~ /01/)' output.txt って感じとか ああ、条件の作成は>>136 の最後ですでにワンライナーで教えているのか。しつれい >>139 そのhoge|fugaはどこから来るの? grep(1)コマンドの結果? >>135 の最初で説明してね?>>135-137 は噛み合ってないだけかなw というか、>>136 の確認/質問のキモがわかってないというか 条件文の | をパイプとかいうからわけわかんなくなる そういう場合はパイプって言わないんですか。失礼しました。 正規表現でつかう or の役割を hoge fuga の間には挟みたいのです。 >>145 >>136 >$ cat ZZZ.txt | grep XXX | tr '\n' '|' | sed 's/|$//1' >↑こういうので行けるけど。違うでしょ? って教えてくれてるやん。「違わない」「それです」でいいんじゃないの?それが違うならどう違うって言うべきかと(どうみても違わないとしか思えないけど) 質問自体がアレだが自分の言いたいことをうまく説明できないのはいいとして、応えてくれてる人の言ってることがわからない/それに応えないのはアレだな awkの手前で別途 fgrep -f か egrep -f を使った方が、改行→「|」変換をサボれて楽な気がする。 fgrep/egrep -f を使うときは bashないし zsh 依存になるけど fgrep -f <(grep XXX ZZZ.txt) と書くともっと楽だね。 \じゃないよバックスラッシュだよ というのがありそうな気もしないでもない シェルスクリプト内で自動で行いたい旨を 書き損じておりました。 cat ZZZ.txt |grep XXX hoge fuga から awk '($3 !~ /hoge|fuga|neko/) && ($4 ~ /01/)' output.txt としたいのです。 >>146 >$ cat ZZZ.txt | grep XXX | tr '\n' '|' | sed 's/|$//1' でまさしく狙い通りの出力がされるのですが>>133 のawkのパターン部にどうかけば同じ文字列が出せるかわかりません awk の文はただの文字列でしかない awk '($3 !~ /'"$aaa"'/) && ($4 ~ /01/)' output.txt でも、 awk "(\$3 !~ /${aaa}/) && (\$4 ~ /01/)" output.txt でも(他にエスケープ必要なのあるかな?)、 普通にシェル変数を(文字列内に)展開するのと変わらんぞ 書き損じどうこうじゃなくて、受け応えができないのが致命的ではあるなw よく見たら、 hoge fuga から hoge|fuga|neko って、nekoはどこから来たっていう。まあうっかりだろけど みなさん申し訳ありません >>150 のレスを見てクォートをよ〜く見なおしたら動きました。 初心者のたわごとに付きあわせてしまい申し訳ありませんでした。 sedコマンドでSGRを扱いたいんですがどうすればいいですか。 $ echo abc | sed 's/^a/\033[1m&\033[0m/1' などとしてaを太字にしたりしたいです。 echo abc | sed -e 's/^a/'$'\033[1m&'$'\033[0m/1' 横からだが、 なんのこっちゃと思ったら $'' はエスケープ文字処理してくれんのね。なるほど 最初のだけでいいのでは?もしくは最初に付ける。もしくは逐一付けて閉じる echo abc | sed -e 's/^a/'$'\033[1m&\033[0m/1' echo abc | sed -e $'s/^a/\033[1m&\033[0m/1' echo abc | sed -e 's/^a/'$'\033''[1m&'$'\033''[0m/1' と思いました ありがとうございます。解決しました。 これは後出しになってしまいますが、POSIXの範囲でやりたかったので $''ではなく$(printf)を使いました。 英語圏の序数詞を適切に処理するシェルスクリプト(というかワンライナー)を考えたのですが添削してください $ for i in $(seq 15); do echo $i$(case $i in *1) echo st;; *2) echo nd;; *3) echo rd;; *) echo th;; esac); done 出力は一応望み通りでまたPOSIX utils+seq(1)のみで実行可能です。 11st とか 12nd になってるけどそれはいいの? すいません。>>161 さまのおっしゃる通りです。 $ for i in $(seq 30); do echo $i$(case $i in *1?) echo th;; *1) echo st;; *2) echo nd;; *3) echo rd;; *) echo th;; esac); done これでどうでしょうか まず添削してくださいってどうしてほしいんだ ちゃんと動いてんならそれはもう正解だと思うんだが >>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とかでいいだろと よくいる偉そうにしたいのが主な目的なのがわいてる感じ ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.1 2024/04/28 Walang Kapalit ★ | Donguri System Team 5ちゃんねる