シェルスクリプト総合 その26 [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
シェルスクリプトの総合スレです。 □お約束 ・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。 Linuxユーザは/bin/shの正体がbashまたはdashなので特に注意。 FreeBSDユーザは/bin/shの正体がashなので注意。 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に逃げずにシェルスクリプトで処理するのが頭のいいやり方。 前スレ シェルスクリプト総合 その25 http://echo.2ch.net/test/read.cgi/unix/1439563321/ >>349 #!/bin/sh IFS=\" while read X Y Z ; do if [ "$X" = "" ] ; then echo -n \"$Y\" | sed 's/,/ /g' echo $Z else echo $X fi done sed '/^"[^"]*"/{H;s///;x;s/\n//;s/^\("[^"]*"\).*/\1/;s/,/ /g;G;s/\n//;}' bashで変数展開するときに、名前末尾にハイフン付けるのはどういう意味なんでしょうか? ${abc-} 今まさにそのページ読んでたけど、:いるよな ナシの使い方なんてあったっけか > コロンを省略した場合には設定されているかどうかのみを調べます。 何度か読み返してようやく理解した unsetされてるか空値が入ってるかの違いに対応出来るのか ログイン時に読み込まれる ~/.profile ファイルは,「誰が」読み込んでいるのでしょうか。 普通 sh もしくはその代替シェルかなと思うのですが,実際はどうなのか気になります。 というのも,私が普段使っている Debian GNU/Linux ではデフォルトシェルは bash に指定しているのですが,~/.profile の中に bash っぽい変数 (${HOGE} という書き方) があったので。 あぁ、すまん >>368 へのレスか たしかに${HOGE}記法はたいていのshで使えるね >>374 何を言ってるのがわからん。bshが元祖なのに。 スレチ気味だけど,ある種の Shell って, $ cd /////// みたいなことをするとルートディレクトリだと認識するんだな。 個人的に ~ がすごく打ちにくい位置にあるので // を ~ だと解釈させようと試行錯誤してるときに発見した。 これはルートディレクトリが特別って訳じゃなく, $ ls /usr////bin/////// みたいなことでも問題ない。ということは // == ~ にすることは Shell のソース弄るくらいしか方法がないということになる。 俺みたいな無駄な努力をしないために残す もしかして RFC とかで実装が統一されてんのか。 $ /bin/echo /usr////bin/////// /usr////bin/////// $ となるので、lsについてはシェルが解釈してるわけではなくlsが解釈していると思われる まあ//を~にしたいならシェルのキーバインド使えばいいんじゃないですかね ちなみにこんなんなったりする シェルの種類によって挙動は違うかも $ cd // $ pwd // $ 理由は http://www.unixguide.net/unix/bash/E10.shtml キーバインドいじっちゃうと 「http:// 」を打とうとして「http:~」になったりして困らないか >>382 「An implementation may」だから必ずではないのでは ファイルをリネームしてコピーし続けるスクリプトなんですが コマンドが見つからないと出てよくわかりません #/bin/sh PATH='/var/log/' PATH2='dnsmasq.log' DOT='.' for i in 6 5 4 3 2 1 do PATH3=$PATH$PATH2$DOT$i PATH4=`expr $i - 1` PATH5=$PATH$PATH2$DOT$PATH4 mv $PATH5 $PATH3 done PATH6=0 mv $PATH$PATH2 $PATH$PATH2$PATH6 exit 0 >>391 for VAR in ARGS; do command; done sh -xで実行してみると以下の通り出力されました + PATH=/var/log/ + PATH2=dnsmasq.log + DOT=. + PATH3=/var/log/dnsmasq.log.6 + expr 6 - 1 ./splitLog.sh: 1: ./splitLog.sh: expr: not found + PATH4= + PATH5=/var/log/dnsmasq.log. + mv /var/log/dnsmasq.log. /var/log/dnsmasq.log.6 ./splitLog.sh: 12: ./splitLog.sh: mv: not found (省略) + PATH3=/var/log/dnsmasq.log.1 + expr 1 - 1 ./splitLog.sh: 1: ./splitLog.sh: expr: not found + PATH4= + PATH5=/var/log/dnsmasq.log. + mv /var/log/dnsmasq.log. /var/log/dnsmasq.log.1 ./splitLog.sh: 12: ./splitLog.sh: mv: not found + PATH6=0 + mv /var/log/dnsmasq.log /var/log/dnsmasq.log0 ./splitLog.sh: 17: ./splitLog.sh: mv: not found + exit 0 とりあえず何がしたいかを書け そんな汚いもん見せられても何がしたいのか分かりにくい PATH潰すんなら外部コマンドはフルパスで書かんと フルパスで書かないといけなかったんですね… 修正してみたらできました、ありがとうございます! ようわからんがsavelogコマンドみたいなことがしたいのか >>396 「フルパスで書かなきゃいけない」のではない $PATHを上書きするのがマズい これ1〜6までファイル全部消えるんじゃね? 5を6にリネーム~0を1にリネーム そのあと最新のログを0にリネームじゃないかな どっちにしろゴリ押し感半端ないが >>399 $PATHって環境変数ですよね… 何故気づかなかったんだろう お恥ずかしい限りです あーそういうことか、403のお陰でやりたいことは分かった こうすればわかりやすいですかね #!/bin/sh DIR=/var/log/ FILE=dnsmasq.log; START=0 for i in `seq 1 6` do DEC=`expr $i - 1` cd $DIR mv "${FILE}.${DEC}" "${FILE}.${i}" done cd $DIR mv $FILE "${FILE}.${START}" exit 0 個人的にexpr嫌いなのもあって$(())使っちゃうな mv "${FILE}.$((i-1))" "${FILE}.$i" あとseq間違ってね? seq 6 1 -1 これだと全部ログ.0になっちゃいますね ありがとうございます! そっちを使うほうが楽、ということを学習するにはまずは自分で書いてみて、大変だぜてことを理解しないと 昔solarisで見たlogrotateはshell scriptだった どこかで見れれば参考になるかも あれはあんまりきれいじゃないから参考にしない方がいい この /usr/lib/newsyslog ね http://www.tcp-ip.or.jp/ ~ikken/intra/check.txt X Windows System で,どの IMF が用いられているか判別する方法を考えている。 思い付いたのは $XMODIFIERS 環境変数を用いた case $XMODIFIERS in   *ibus)     local _imf=ibus     ;;   *fcitx)     local _imf=fcitx     ;;   *uim)     local _imf=uim     ;;   *SCIM)     local _imf=scim     ;; esac なんだけど,$XMODIFIERS が必ず設定されているとは限らないし,なんか漏らしてる気がしてならん……。 ツールで投稿したら空白がエラいことになった。すまん。 Shell Scriptのコメントアウトに # @(#) Foo is foo. みたいな文字を書いておいて $ what ./foo.sh とやると Foo is foo という表示がでるというようなwhatコマンドがあるらしいのですが 手元のFedora26に見付かりません。($ dnf search what, $ dnf provides what) どこかにありますでしょうか。 >>420 whatはかつて使われていたSCCSというソースコード管理システムに入っていたコマンド 現在はGNU CSSCがSCCSと同等の機能を提供している なのでcsscというパッケージを探す なければhttps://www.gnu.org/software/cssc/ へGO! case文で $1がhogeで、$2がhageの場合のみ処理Aを実行する みたいなのできないでしょうか? $1にも$2にも含まれ得ない文字を区切りにして連結 >>422 ありがとうございます。依存地獄に嵌ってしまいあきらめました,教えてもらったのにすいません。 また,御礼がおそくなってもうしわけないです。 caseで実装するなら入れ子かね しかしここでも髪の話するのか >>424 >>425 >>427 入れ子にできることを全然知らず こんな感じかなでやってみたらいけました 皆さん短時間にありがとうございます >>427 他意はありませんw すみません、bashでタブ区切りのファイルを配列に取り込む際、空の列が詰めて格納されてしまいます そうならない方法はあるのでしょうか exec < file.tsv while read LINE do ARRAY=(${LINE}) done >>430 変数の参照部分を引用符で囲むとか。 #!/bin/sh - exec < file.tsv while read LINE; do ARRAY=("$LINE") done echo "$ARRAY" IFS の値を空にするとか。 #!/bin/sh - IFS= exec < file.tsv while read LINE; do ARRAY=($LINE) done echo $ARRAY あ,5ch ってコード貼るのまずいんだっけ。しくったな。 まあこんなくだらないコードに著作権云々関係ないかw >>430 bash なら mapfile がある(別名 readarray) -t オプションで各行末尾の改行を取除く mapfile -t ARRAY <file.tsv 検証した結果、IFSを改行のみにして読み込み、その文字列をCutで抜くで達成できました こうしないと空文字の列が詰まってしまいました IFS_BAK=IFS IFS=$'¥n' exec < file.tsv while read LINE do echo "${LINE}" | cut -f1 >> tmp1.txt echo "${LINE}" | cut -f2 >> tmp2.txt done IFS=IFS_BAK >>435 重箱の隅を突くようで悪いが,その書き方をするならシェバンは #!/usr/bin/bash にしておけ。 $'string' は Bash の独自拡張だった気がする。 >>430 今ごろ勘違いに気づいた mapfileじゃ全然見当外れじゃないか…なんかごめん たとえば IFS=$'\t' line="${IFS}b" このとき a=(${line}) で a=("" "b") となるのを期待しているのだけど、実際にはクオートしていないので a=( b) と同じことになって、先頭の「空の列」は残らない かといってクオートしたら a=("${line}") これはタブ区切りで分割されることなく行全体がそのままになるので意味がない… ということだよね >>435 のようにファイルに書き出すだけなら、そうやってcutでやるのが扱いやすそうだけど もしどうしても配列にする必要があるときは、こんな感じでどうだろう https://ideone.com/uPfCwc 空だと消えてしまうなら空にならないよう何か入れとけばいいじゃない(配列にしてから取り除く) という案 >>437 回答が遅れてすみませんでした なるほど…その手はいけるんですね ありがとうございます、活用させていただきます 自分は今回縛りがあってbashだけでやっているのですが、可能なら他のスクリプトに任すべきかな…(´・ω・`) 誰でも簡単にパソコン1台で稼げる方法など 参考までに、 ⇒ 『宮本のゴウリエセレレ』 というブログで見ることができるらしいです。 グーグル検索⇒『宮本のゴウリエセレレ』 PPEE18BYYA はじめまして 早速で申し訳ないのですが、以下のシェルスクリプトでdoを含むコマンドが一切使用できません。理由と解決策を教えてください。 #!/bin/sh dir=`dirname ${0}` echo -n "探す拡張子=" read que ans=$(find ${dir} -name *.${que} | awk -F/ '{print $NF}') if [ -z "${ans}" ];then echo "${que}は見つかりませんでした。\n終了します。" exit else echo "${ans}" fi >>441 すみません訂正します。 select文のみどこに書いてもSyntax error: "do" unexpectedというエラー出てしまいます。 doが何のこと言ってるのかよくわからんが実行の仕方が間違ってんじゃね まず問題がどこにあるかを明確に切り分けろ >>443 さっき書き直したのですが、改善しませんでした。 エラー内容はさっきと同じで、 Syntax error: "do" unexpectedです。 441でも、どこに記述しても変わらなかったため、問題の部分を消して使っていたので、doの部分を貼り忘れてました。すみませんでした。 #!/bin/sh dir=`dirname ${0}` echo -n "検索する拡張子:" read que while [ -z "${que}" ] do #ここのdoは問題なし。 echo -n "拡張子を入力してください。\n検索する拡張子:" read que done ans=$(find ${dir} -name *.${que} | awk -F/ '{print $NF}') if [ -z "${ans}" ];then echo "${que}は見つかりませんでした。\n終了します。" exit else echo "${ans}" fi #============ここから問題の部分=========== select var in ${ans}終了 do if [ ${var} = 終了 ];then exit fi if [ ${que} = gz -o xz];then tar -xf ${dir}${var} fi done xz ]やないの? シンタックスエラーって出てるんだからまず自分を疑おう どこに貼ってもだめならselectの構文がなんかおかしいんじゃないの >>445 スペース入れても変わりませんでした。 >>446 構文がおかしい部分を自分では見つけられませんでした。 do unexpectedなら直前の「${ans}終了」ちゃうんけ >>448 変数じゃなくしても、終了を消しても、別の変数に変えてもSyntax error: "do" unexpectedは消えませんでした。 とりあえず「間違いなく動作する」select構文をまず単品で書け ネットのコピペでも構わん。出来る限りシンプルなやつで 動いたならそれを少しずつ改造して動かしてを繰り返しつつお前の目的に近づけろ SC2039: In POSIX sh, select loops are undefined. bashならとりあえず動く、#!/bin/bash にしとけば >>450 ありがとうございます。コピペ&作り直しでできました。 >>451 Ubuntuでやっていたのでできました。 >>452 書き換えました。 皆様ありがとうございました。 もしかしたら似たようなものがすでにあるかもしれませんが、とりあえずできたものを>>454 に貼っておきます。 #!/bin/bash PS3="入力してください:" menu="曖昧 前方一致 後方一致 完全一致 拡張子" echo "検索するディレクトリを入力してください 入力しなかった場合、このファイルがあるディレクトリを検索します。" while [ -z "${dir}" ] do echo -n "ディレクトリ入力:" read dir if [ -e "${dir}" ];then break else unset dir echo "そのようなディレクトリはありません。" fi done echo "検索方法を選択してください:" >>455 に続く >>454 続き select var in ${menu} do echo ["${var}"]で検索します。 echo -n "検索する単語を入力してください:" read que case "${var}" in 曖昧) ans=$(find ${dir} -name *"${que}"*);; 前方一致) ans=$(find ${dir} -name "${que}"*);; 後方一致) ans=$(find ${dir} -name *"${que}");; 完全一致) ans=$(find ${dir} -name "${que}");; 拡張子) ans=$(find ${dir} -name *."${que}");; esac echo "${ans}" exit done 正直見辛いしその程度なら一行コマンド打つんでいらないっす ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる