• ベストアンサー
  • 困ってます

シェルスクリプト shiftとwhile

下記の内容はスクリプトの一部を抜粋した内容です。 2箇所、理解が出来ない部分があるので、教えて頂けますでしょうか。 ------------------------------------------------ shift $(( $OPTIND -1)) if [ $# -eq 0 ]; then FileName="" elif [ $# -eq 1 ]; then if [ "\-" = "$1" ]; then FileName="" else FileName="$1" fi else echo "オプションが多い" exit fi if [ "" = "$FileName" ]; then while read line; do fcnctionA "$line" done else while read line; do fcnctionA "$line" done < "$FileName" fi ------------------------------------------------ (1) if [ "\-" = "$1" ]; then 部分が理解できないのですが、教えて頂けますでしょうか。 (2)  if [ "" = "$FileName" ]; then while read line; do fcnctionA "$line" done 基本はファイル名を指定して実行する事を前提としていると思います。 ファイル名を指定しないでスクリプトの実行をする場合は、1行ずつ標準入力で 入力すると思うのですが、このような使い方をする場合はあるのでしょうか。 下記よりも便利な点があるようでしたら、教えて頂けますでしょうか。 または、shiftと関係があるのでしょうか? if [ ! "" = "$FileName" ]; then while read line; do fcnctionA "$line" done < "$FileName" fi

共感・応援の気持ちを伝えよう!

質問者が選んだベストアンサー

  • ベストアンサー
  • 回答No.1
  • notnot
  • ベストアンサー率47% (4771/10078)

(1) 「第一引数が、\- であれば」という意味です。 普通は、\- でなく - と比較すると思います。 (2) 普通です。 「引数にファイル名があればそのファイルから読むし、引数が - であるか、ファイル名の引数が無い場合は標準入力から読む」というコマンドはたくさんあります。 cat とか、grep とか sed とか、いくらでも。 shiftとは関係ありません。shift は、このコードの前にある getopts と関係しています。 このコードは初心者の書いたものですね。shiftの後の部分は、引数の個数のエラー処理を除くと、次のように1行で書くのが普通でしょう。 cat "$@" | xargs -n 1 fcnctionA

共感・感謝の気持ちを伝えよう!

質問者からのお礼

(1) 「-」が引数なしと同じ意味で、標準入力の扱いになるんですね。 ネットで調べたのですが、見つけられなくて困っておりました。 (2) かなりコンパクトになりますね。 勉強になりました。ありがとうございます。

関連するQ&A

  • シェルスクリプトでwhileを用いてrshを繰り返し使う場合

    Bシェルスクリプトでリモートシェル(rsh)を使う場合の質問です。 現在、以下のような状態です。 有識者の方、アドバイスをお願いします。 ・Aでは、ループされずhostAの場合のみ処理がされます。 (while文が効いていない) ・Bでは、ループされて問題なくhostA,hostB,hostCが処理されます。 (while文が効いている) なぜなのでしょうか。。。(r系コマンドの特性?) ちなみり、リモート側のサーバには.rhostsが設定してあり 問題なくコマンドが通ることは確認済みです。 スクリプトA---------------------------------------------- #!/bin/sh while read line ; do rsh $line hostname done <<END hostA hostB hostC END スクリプトA---------------------------------------------- スクリプトB---------------------------------------------- #!/bin/sh while read line ; do echo " HOST=$line" done <<END hostA hostB hostC END スクリプトB----------------------------------------------

  • 行頭が数字の行を表示するシェルスクリプト

    最近シェルスクリプトの勉強をはじめまして、一度自分で作ってみようと思い 行頭が数字の行を表示するシェルスクリプトを書いてみました。 が、うまく出来ません。 表示させたいファイルは字幕ファイルの始めの10行程度で内容は以下の様になってます 1 00:00:03,600 --> 00:00:07,195 xxxxxxxxxxxxxx xxxxxxxxxxxxxx 2 00:00:07,360 --> 00:00:09,635 xxxxxxxxxxxxxx xxxxxxxxxxxxxx     ・       ・     ・ xxxxxxxxxxxxxの部分には英語の台詞が入ります。 以下が自分で作ってみたスクリプトです。 #!/bin/bash while read Line do if [ "$Line" eq [0-9][0-9] ] then echo $Line else : fi done < $1 表示させたいのは行頭が数字の行なので自分の望む結果は 1 2 3 ・ ・ ・ です。 初歩的な間違いかもしれませんが、自分にはどこが間違っているのか分かりません。 酷いスクリプトかもしれませんが、一応完成させてみたいのでご指導お願いしますm(_ _)m

  • シェルスクリプト

    2月14日頃質問のあった”UNIXのシェルスクリプトを使用してテキストファイルのある列にある特定の文字列を条件としてその行を出力するということをやりたい”を下記のように作ってみました。問題ないか逆質問の形で投稿します。(ルール違反かもしれませんが質問が締め切られているので・・・) #!/bin/bash CAT=YAHOO while read LINE do echo $LINE > tmp.txt DOG=`cut -d" " -f2 tmp.txt` if [ "$CAT" = "$DOG" ] then echo "$LINE" fi done < catalog.file

  • スクリプトの修正お願いします。

    ================スクリプト内容(sample)===================== #!/bin/sh # ls -l /home/sendfile/ > /tmp/dellist awk '{print $6"\t"$7"\t"$9}' /tmp/dellist > /tmp/list awk -v ARGUMENT="$1" ' BEGIN{ MON=substr(ARGUMENT,1,1) * 10 \ + substr(ARGUMENT,2,1) DAT=substr(ARGUMENT,4,1) * 10 \ + substr(ARGUMENT,5,1) } { echo $MON $DAT if ( "$1" -eq "Jan");then CMON=1 elif ( "$1" -eq "Feb" );then CMON=2 elif ( "%1" -eq "Mar" );then CMON=3 elif ( "%1" -eq "Apr" );then CMON=4 elif ( "$1" -eq "May" );then CMON=5 elif ( "%1" -eq "Jun" );then CMON=6 elif ( "%1" -eq "Jul" );then CMON=7 elif ( "%1" -eq "Aug" );then CMON=8 elif ( "%1" -eq "Sep" );then CMON=9 elif ( "$1" -eq "Oct" );then CMON=10 elif ( "%1" -eq "Nov" );then CMON=11 elif ( "%1" -eq "Dec" );then CMON=12 fi CDAT=substr($2) if [ [ MON > CMON ] || [ ( MON = CMON ) && ( DAT > CDAT ) ] ] {print} }' /tmp/dotFAX/list > /tmp/dotFAX/dellist ================ 実行 ===================== $ sample "08/07/06" ================ 上記の実行結果 ===================== awk: cmd. line:36: fatal: 1 is invalid as number of arguments for substr のようなErrが出ていますが、原因が分かりません。 間違っている箇所や修正お願いします。

  • Kシェルでの read line と awk

    お世話になっております。 AIX の 標準 kshell にて下記を実行したいと考えております。 <やりたいこと> recode.txt(逐一別のシェルで内容は変更される) の中身に書かれている文字を参照して、test.txt を読み込んで該当する文字列を読み込みたいと考えています。 test.txt は編集可能なので、誤記入対策の為に、空白/タブ行、先頭空白/タブ、行末空白/タブを無視出来るようにしたいと考えています。 例) recode.txt AAAAA test.txt # ~~コメント~~ # ~~コメント~~ # ~~コメント~~ # ~~コメント~~ <AAAAA> test1 test2 test3 <BBBBB> test10 test11 test12 test13 この場合、結果として、test1、test2、test3を得て、このファイルに対して別のシェルを実行したいと思っております。 recode.txt は read line を使って読み込めるのですが、とりあえずテストとして下記のように test.txt を awk( print $1 で先頭空白、先頭タブが無視されるようでしたので) をつかってみたのですが、上手くいきませんでした。 上手くいかないというよりは、「elif [[ ${jug} == "A" ]]; then」の elif がおかしいと言われ、どうも if ~ の部分がおかしいっぽいのですが……すいません、自分ではどうも原因が分からず困っております。 【test.ksh】 (~省略~) (recode.txt 読み込み処理) jug=X while read line ; do if [[ "`awk '{print $1}' ${line}`" == "#" || "`awk '{print $1}' ${line}`" == "" ]]; then elif [[ ${jug} == "A" ]]; then if [[ `awk '{print $1}' ${line}`" == "<BBBBB>" ]]; then break fi test2.ksh ${line} <エラーチェック> elif [[ ${jug} == "B" ]]; then test3.ksh ${line} <エラーチェック> elif [[ "`awk '{print $1}' ${line}`" == "<AAAAA>" and ${recode} == "AAAAA" ]]; then jug=A elif [[ "`awk '{print $1}' ${line}`" == "<BBBBB>" and ${recode} == "BBBBB" ]]; then jug=B fi done < test.txt (~省略~) $line の扱いが間違っているのか、それとも構文的なところなのか…… orz 本業がSEじゃないのでシェルに詳しくなく申し訳ないのですが、基本的なことと存じますが教えて頂けますと幸いです。 宜しくお願い致します。 ※投稿時に先頭空白が上手く処理されないようで、回避方法が解らず、全て左につめられてしまいまして見難く申し訳ありません。

  • zenityを使ったシェルスクリプトについて

    zenityを使ったシェルスクリプトを作りたいのですが、どう書けば良いのかわかりません。ちなみにbashです。 行いたいのはzenityを使って2回質問をし、2回ともOKだった場合に最終的に行いたいコマンドの実行をするというものです。 単純にif文を2回繰り返せば良いのでしょうが、書き方がわかりません。 以下のような具合になるのでしょうか? #!/bin/bash a=$(zenity --question --title "shred" --text "よろしいですか?"); if [ $? -eq 0] then a=$(zenity --question --title "shred" --text "本当によろしいですか?"); if [ $? -eq 0 ] then gedit $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS fi fi

  • シェルスクリプトにおけるreadコマンドについて

    シェルから読み込まれる"param_file"において、 A B といった途中に空白を含む行が存在する場合、 while read PARAM if [ $1 = ${PARAM} ] then break fi done < "param_file" を実行すると if文実行時に "too many arguments"エラーが発生します。 Solalis上で同じ処理を実行してもエラーが 発生ませんが、Linux特有なのでしょうか。

  • シェルスクリプトエラーになります。

    はじめまして、初心者なので失礼な書き方でしたらご容赦願います。 下記のようなシェルスクリプトを書きました。 実行したところエラーになります。 何がいけなく、正しくはどう記述すればよろしいでしょうか? 何卒ご教授願します。 ===========================ここから=============================== #!/bin/sh test1=12345 test2=678 if ${test1} -eq ${test2} then echo "eq:数値1と数値2が等しい場合に真" echo "test1の「${test1}」と、test2の「${test2}」は等しい" fi if ${test1} -ne ${test2} then echo "en:数値1と数値2が等しくない場合に真" echo "test1の「${test1}」と、test2の「${test2}」は等しくない" fi echo "********* テスト完了 *********" ===========================ここまで============================== ======================実行結果エラーここから======================== $ ./testsh110204.sh ./testsh110204.sh: line 6: 12345: command not found ./testsh110204.sh: line 12: 12345: command not found ********* テスト完了 ********* ======================実行結果エラーここまで======================

  • シェルスクリプトの関数

    #!/usr/bin/bash SOURCEBASE="`echo \"$1\" | sed 's/\.[^.]*$//'`" DOCLEAN='no' # 「-c」オプションで削除するファイルの拡張子一覧 CLEANEXTS='aux log toc lof lot bbl blg idx ind ilg' show_help() {   cat <<EOF autolatex [options] latex-source[.tex]  -c  Clean temporary files before typesetting EOF   exit 1 } do_clean() {   for ext in $CLEANEXTS; do    if [ -f ${SOURCEBASE}.${ext} ] ; then      echo "hoge1"      echo ${SOURCEBASE}.${ext}      rm ${SOURCEBASE}.${ext}    fi   done } if [ $# -eq 0 ] ; then  show_help  exit 1 fi while getopts c: flag; do   case ${flag} in   c) DOCLEAN='yes';;   \?) exit 1;;   esac done do_clean #if [ ${DOCLEAN} = 'yes' ] ;then # # echo "hoge2" # do_clean #fi やりたいこととしては*.auxや*.logファイルを-cのオプションをつけた時に削除されることです. とりあえず手始めに取り合えず動くかの確認をしました $ bash test.sh hoge.tex hoge1 hoge.aux hoge1 hoge.log 次にコメントアウトしている部分を取り除いて(さらにその上にあるdo_cleanもコメントアウトします) #do_clean if [ ${DOCLEAN} = 'yes' ] ;then  echo "hoge2"  do_clean fi $ bash test.sh -c hoge.tex hoge2 同様に実行しました.結果は上のようになりif分はtrueで認識されているのですが,その次のdo_cleanでecho部分でのhoge1が表示されません. if分で分岐させている時は関数を別の呼び方で呼ばないといけないのでしょうか? さらに, do_clean if [ ${DOCLEAN} = 'yes' ] ;then  echo "hoge2"  # do_clean fi このようにしても結果は変わりませんでした. (オプションでなにか気をつけなければならない?) オプションをつけたときだけ該当するファイルを削除したいです,ご教授ねがいます><(なお空白はすべて全角空白になっています)

  • シェルスクリプト while のループを止めるには

    サーバA 192.168.1.201(プライマリ) 192.168.1.203(セカンダリ) サーバB 192.168.1.202 サーバBより、サーバA(192.168.1.201)へ定期的にPINGの監視をシェルスクリプトで行います。 192.168.1.201より、PINGの返答がない場合は、サーバBがサーバAのプライマリサーバのIPアドレスを 引き継ぎます。(ここまではシェルでうまくできました。) サーバBはそのまま次にサーバAのセカンダリ(192.168.1.203)に対してPINGを行います。(これは永遠と192.168.1.203より返答がなくなるまで行います。) そして、192.168.1.203より返答がなくなった場合、サーバBは自身の元のIPアドレスへと戻します。 上記内容を下記のようにシェルスクリプトで作成したのですが、下記のようにすると永遠とネットワークが再起動を繰り返し続けてしまい、困っております。 これを止めるには一体何を足せば良いのでしょうか…。 #!/bin/sh TARGET_IP='192.168.1.201'; for ip in $TARGET_IP; do ping $ip -c 4 if [ $? -ne 0 ]; then echo "PING ERROR" ifconfig eth0 192.168.1.201 arp -d 192.168.1.201 #ping にて 100% loss があった場合は、コマンド実行です。 #返答があった場合は、そのまま ping させ続けます。 while [ -n "$(ping -c 1 192.168.1.203 | grep 100%)" ] do echo "Primary server comes back" /etc/init.d/networking restart done fi; done