マンガでよめる痔のこと・薬のこと

いつもお世話になっております。
宜しく御願い致します。

if文で数値判断により条件分岐をしようと思ってます。

条件は”0<変数<=20”(仮)で、エラーだと警告文表示後に変数入力部に戻したいのです。

変数を画面上から”変数 = $<”で読み込み、処理をしたいのですが、うまくいきません。

整数値だとうまく行く方法を見つけましたが、小数値が入るとNG、小数値でもうまく行く方法を見つけました(bcを使用)が、文字列が入力されるとNG、と行き詰まってしまいました。

入力値としては小数値を期待しているのですが、操作する人が間違って”3..2”や”2 5”、”4rr”等が入力された場合も偽の判断をもって処理を戻したいのですが、ifの形式がおかしいとか、文法上のエラーがあると表示され、うまく戻ってくれません。

なにか良い方法はないでしょうか?

要は、if(変数 > 0 && 変数 <= 20) then で変数の値が文字列、小数、整数問わずに処理をしたいだけなんですが・・・。

どうぞ宜しく御願いします。

このQ&Aに関連する最新のQ&A

A 回答 (4件)

expr等を使って正規表現で判断するしかないでしょうね。

\| の前が小数値、後ろが整数値のチェックです。
expr以外でも正規表現が使えるコマンドなら何でもいいですが。

expr "$var" : '[0-9][0-9]*\.[0-9][0-9]*$' \| "$var" : '[0-9][0-9]*$' >/dev/null

if( $status == 0 ) then
 正常処理
else
 エラー処理
endif
    • good
    • 0
この回答へのお礼

詳細な回答有難うございます。
このようなやり方は想像つきませんでしたが、条件をたくさん設定して、エラー入力を回避するしかないみたいですね・・・。参考にさせて頂きます。

お礼日時:2006/04/04 10:19

文法エラーのメッセージを /dev/null に捨てたらどうですか。



あるいは、一旦 exprコマンドで数値としての形式を取っているか確かめてから、cshのif文を行うとか。

いずれにせよ、シェルスクリプトをcshで書くことはお薦めできません。
cshは対話利用にとどめてshで書く方が良いと思いますよ。
    • good
    • 0
この回答へのお礼

回答有難うございます。cshはいまいちですか・・・。
検討してみます。

お礼日時:2006/04/04 10:20

Perlでコーディングすれば問題ないですよ。

    • good
    • 0
この回答へのお礼

回答有難うございます。
Perlはまだ勉強不足で、やってはみましたがやはり条件設定をたくさんしなければだめでした。

お礼日時:2006/04/04 10:22

数値に見えないようなものは先に除外してから bc に送り込めばいいのでは?

この回答への補足

回答有難うございます。
それも考えたのですが・・・。
除外するための何か良い方法はありませんか?
変数を一度ファイルに取り込んでtrで変換とか考えたのですがどうもスマートでないので止めました。
if文のなかではメタキャラクタもうまく使えなくて英字の削除ができません。”.”や空白の処理もどうしたものかと思い、またまた現在作業停滞中でございます・・・。

補足日時:2006/04/03 19:30
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qシェルスクリプトでファイル内の数値文字列を数値として扱うには

失礼します。
シェルスクリプトでファイル内のテキスト(数値文字列)を取得して、それを使って計算するにはどうすれば良いでしょうか?

str:ファイル内のテキスト(数値文字列)

res=$(( $str + 1 ))

・エラー
")syntax error: invalid arithmetic operator (error token is "


よろしくお願いします。

Aベストアンサー

bashをご使用と判断して

res=$(( $str + 1 ))
ではなく、
res=$(( str + 1 ))
だと思います。

> exprもやってみたのですが、処理が遅くなるので使いません。
興味があって以下のシェルで検証してみました。

#!/bin/bash

str=1
i=0

echo 'Using $((str + 1))'
date '+%H:%M:%S.%N'

while [ $i -lt 10000 ]
do
str=$(( str + 1))
i=`expr $i + 1`
done

date '+%H:%M:%S.%N'

exit

$ ./test.sh
Using $((str + 1))
09:18:46.290418000
09:18:56.929345000
これをexprに書き換えたところ
$ ./test2.sh
Using expr
09:19:00.302748000
09:19:19.259990000

exprだと19秒ですが、$(( 演算 )) だと10秒程度なので、演算が多くなれば確かにexprは不利ですね。

bashをご使用と判断して

res=$(( $str + 1 ))
ではなく、
res=$(( str + 1 ))
だと思います。

> exprもやってみたのですが、処理が遅くなるので使いません。
興味があって以下のシェルで検証してみました。

#!/bin/bash

str=1
i=0

echo 'Using $((str + 1))'
date '+%H:%M:%S.%N'

while [ $i -lt 10000 ]
do
str=$(( str + 1))
i=`expr $i + 1`
done

date '+%H:%M:%S.%N'

exit

$ ./test.sh
Using $((str + 1))
09:18:46.290418000
09:18:56.929345000
これをe...続きを読む

Qcshの文字列操作(0埋め)

ヤマトです。

cshの文字列操作について質問します。
環境はRed Had Linux7.2です。

数値を文字列に変換し、更に0埋めするのはどのようにしたら良いのでしょうか?
以下に例を書きます。

====SAMPLE.sh(一部抜粋)====
@ NUM_AAA = 1
ECHO NUM_AAA
set CHR_AAA = ×××××
ECHO CHR_AAA

====SAMPLE.sh(実行結果)====
1
01

以上の ××××× に当てはまる処理が分かりません。
C言語とかで言うなら、sprintf のような処理をしたいのですが。

どのようにしたら良いのでしょうか?
教えて頂けると有り難く思います。宜しくお願いします。

Aベストアンサー

/usr/bin/printf があれば以下でOKです。

set CHA_AAA=`printf "%02d" $NUM_AAA`

「"%02d"」の部分の指定方法は、C言語のprintf、sprintfとだいたい同じです。

Qcshで文字列分割

ヤマトです。

cshの文字列分割について質問します。
環境はRed Had Linux7.2です。

set DATA = hoge1;hoge2;hoge3
のデータを";"区切りでDATA_ARR(配列)に入れたいのですが、分かりません。
調べた所、[awk]と[split]を使えばできるようなのですが、
実際どのようにSHに記述していいか分かりません。
n = split(DATA,DATA_ARR,";")
をどのように記述したらよいのでしょう?

教えて頂けると有り難く思います。宜しくお願いします。

Aベストアンサー

こんにちは、ヤマトさん。

csh の配列というのは、例えば DATA が「foo;bar;baz」であったとき、
DATA_ARR には「foo bar baz」という値を入れたいということでいいでしょうか。

split を使えばこのようになりますか。最後には Control-D を押す必要があります。
この例では split の結果は配列 A の中に格納されます。
「DATA=$DATA」はシェル変数 DATA の値を
AWK で用いる変数 DATA に代入するという意味です。

set DATA_ARR=`awk 'END{split(DATA,A,";");print A[1],A[2],A[3]}' DATA=$DATA`

split を使わない別解として、標準入力を用い

set DATA_ARR=`echo $DATA | awk 'BEGIN{FS=";"}{print $1, $2, $3}'`

とも書けます。こちらは C-d は不要です。

BEGIN 節の中の「FS」とはフィールド区切り文字(field separator)の意味で、
AWK は $0 をこの値によって自動的に split してくれます。

なお、FS については BEGIN 節の中で記述せず、
「-F\;」のようにAWK へのオプションとしても指定できます。
(「;」をエスケープしていることにご注意)

「OFS」という出力フィールド区切り文字(output FS)もあり、
print などの出力はこれを挟んで表示されます。
初期値はスペースで、上記の例でもこの初期値を利用しています。

結果は「echo $DATA_ARR[1]」などとしてご確認ください。

独習されているようですので、いい参考書が必要でしょう。
「LINUX クイックリファレンス(第2版)」(オライリー・ジャパン)がお勧めです。
この1冊の中に各種シェルや awk, perl、GNU コマンドなどが要領よく解説されています。
お値段は高めですが、それだけの値打ちはあると信じます。
http://www.oreilly.co.jp/BOOK/linuxnut2/

AWK の参考書としては同じくオライリー・ジャパンの「sed&awk プログラミング 改訂版」
(Dougherty, Robbins 共著、福崎 俊博訳)か、
「プログラミング言語 AWK」(エイホ・カーニハン・ワインバーガー共著、
足立高徳訳/シイエム・シイ)がいいでしょう。
ちなみに「AWK」の名前の由来はこの三人 Aho, Weinberger, Kernighan の
頭文字を取ったものです。
http://www.oreilly.co.jp/BOOK/sedawk/
http://www.amazon.co.jp/exec/obidos/ASIN/4901280406/ref%3Dase%5Fseshopcom-22/250-8600902-9060234

スクリプト言語として AWK もいいのですが、基本的にフィルタ言語ですから
制御構造が標準入力を読み込むためのループに縛られる傾向があります。
今から学ぶとしたら、Ruby や Perl または Python の方がよりやり甲斐があると思います。
特に私の好きな Ruby ではこのように書けます。

ruby -e "print '$DATA'.split(/;/).join(' ')"

(ba)sh においては以下のようにしてください。

ruby -e "print \"$DATA\".split(/;/).join(' ')"

join は split の逆で、配列要素を区切り文字で挟んだ文字列を返します。

split の括弧の中身がシンプルなのがおわかりでしょうか。
左から右へすんなりと処理が進んでいくのは、
Ruby の「オブジェクト指向」の御利益なのです。
http://www.ruby-lang.org/ja/
http://www15.web24.jp/~c01763n1/rubytips/

最後にちょっとお節介。
csh を使ってみて、やっぱり込み入った引用符の処理が
(ba)sh に比べて洗練されていないと感じました。
最後の Ruby の実行例でも、''で囲まれて展開されないはずの $DATA が
実際には展開されたり、エスケープしたはずの「"」が
実際にはされなくてエラーになったりしました。
bash ではちゃんと思い通りの結果が得られます。

シェルスクリプト言語としては、sh をお使いになった方が
リダイレクションなどいろいろと楽だと思います。
http://faqs.jmas.co.jp/FAQs/csh-whynot-jp

bash でもバージョン2から配列が使えるようになっています。
表記は「${DATA_ARR[1]}」のようになります。あ、「man gawk」も忘れずに。

http://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/awk/intro/

参考URL:http://aoki2.si.gunma-u.ac.jp/Hanasi/Algo/awk.html,http://www.kt.rim.or.jp/~kbk/gawk-30/gawk_toc.html

こんにちは、ヤマトさん。

csh の配列というのは、例えば DATA が「foo;bar;baz」であったとき、
DATA_ARR には「foo bar baz」という値を入れたいということでいいでしょうか。

split を使えばこのようになりますか。最後には Control-D を押す必要があります。
この例では split の結果は配列 A の中に格納されます。
「DATA=$DATA」はシェル変数 DATA の値を
AWK で用いる変数 DATA に代入するという意味です。

set DATA_ARR=`awk 'END{split(DATA,A,";");print A[1],A[2],A[3]}' DATA=$DATA`

...続きを読む

QCシェル内でBシェルの様な関数の記述方法はありますか?

タイトル通り、Cシェル内でBシェルの様な関数の記述方法はありますか?

Bシェルで言う所の以下の様な記述方法です。

関数()
{

}

OSはSolarisです。

よろしくお願いいたします。

Aベストアンサー

cshには関数はありません。tcshも同じだと思います。
関数部分を別ファイルにして、sourceコマンドで呼び出すくらいしかないでしょう。
cshは大規模なスクリプトには向かないと思います。

Qシェルの引数の入力チェックをしたい・・

シェルは初心者のため、ご教授ください。

3つの引数を受け取り、値のチェックを行いたいのですが書き方がよくわかりません・・。

やりたいチェックは、
第1引数は 数字じゃなければエラー
第2引数は 文字列が "YES" か "NO"でなければエラー
第3引数は 日付のフォーマットチェック(YYYY/MM/DD以外はエラー)
です。よろしくお願いします。

Aベストアンサー

1)数字以外を削除して元と同じなら数字のみだとわかる

A=`echo "$1" | sed 's/[^0-9]//g'`
if test "$1" = "$A"
then echo 数字だけ
else echo エラー
fi

2)
if test "$2" = YES -o "$2" = NO
then echo YES か NO
else echo エラー
fi

3)
これは難しい。gnu date (Linux等のdate)を前提とすれば出来ます。
A=`date +%Y/%m/%d -d "$3"`
if test "$3" = "$A"
then echo YYYY/MM/DD形式の日付データ
else echo エラー
fi

gnu date が無いと、大の月・小の月・うるう年などを地道に調べる必要あり。

Q数値かどうかの判定方法

$aに代入されているものが数値かどうかを判定するにはどのようにしたらよいのでしょうか?

Aベストアンサー

$a =~ /^[0-9]*$/
上記の場合、*は「直前のパターンの0回以上の繰り返し」の意味なので、0から9がなくても、つまり$aが空でもマッチしてしまいます。
なので、
$a =~ /^[0-9]+$/
としましょう。
(+は「直前のパターンの1回以上の繰り返し」)
また、0-9は\dで表すこともできるので
$a =~ /^\d+$/
と書くこともできます。

Qsedの置換文字に変数を使用したいのですが・・・

あるファイルの特定の文字を変換し、上書きをする処理を行いたいのですが、sedの置換文字に変数が渡せなくて困っています。

例:
X="a"
Y="b"
echo test.txt | sed 's/${X}/${Y/g}' >test.txt

sedでは置換文字に${X}といった変数を使用することはできないのでしょうか?

Aベストアンサー

' ・・・' で囲まれた中の$はそのままドルマークです。変数展開をするなら、'・・・'で囲んではいけません。

何も囲まないか、"・・・"で囲むかです。

QCシェルでの文字列大小比較

Cシェルで
set AA="aa"
set BB="bb"
if( $AA > $BB )then
echo "$AA > $BB"
endif
というような判定がしたいのですが、
上記の場合、”if: 条件式構文が正しくありません”というエラーが出力されます。
Cシェルの場合、文字列の比較は
ifでイコールかノットイコールかは判定できますが、文字コードの大小比較が出来ないようですが、
文字列の大小比較をするにはどうすればよいのしょうか

Aベストアンサー

expr コマンドが使えます。コマンドを if の条件式で使うときは、{ } で囲みます。

if({ expr "$AA" \> "$BB" >/dev/null }) then
.....
endif

ただし、$AA $BB ともに数字のときは数値として比較するので、常に文字列として比較したいなら、
expr A"$AA" \> A"$BB" >/dev/null
のように両方の先頭に同じ文字をくっつければ$AAが数値でも全体としては数値じゃなくなるので文字列比較になります。

expr 2 \> 10   →偽
expr A2 \> A10  →真

Qcshの条件式について教えてください

cshで該当ディレクトリにファイルがなければOK、あればエラーというような処理をしようと思っています。

しかし、下記のような記述ではうまくできません。
1)
***************************
if ( -e $DIR/*.* ) then
echo "NG"
exit 1
else
echo "OK"
endif

exit 0
***************************

if文でなく、外にだせばうまくいくのですが...
2)
***************************
test -e $DIR/*.*
if($status == 0) then
echo "NG"
exit 1
else
echo "OK"
endif
exit 0
****************************

if ( test -e $DIR/*.* ) then...
でもだめでした。

どうにかしてif文で一発判定をしたいと思っているのですが、正しい記述方法を教えてください。

よろしくお願いします。

cshで該当ディレクトリにファイルがなければOK、あればエラーというような処理をしようと思っています。

しかし、下記のような記述ではうまくできません。
1)
***************************
if ( -e $DIR/*.* ) then
echo "NG"
exit 1
else
echo "OK"
endif

exit 0
***************************

if文でなく、外にだせばうまくいくのですが...
2)
***************************
test -e $DIR/*.*
if($status == 0) then
echo "NG"
exit 1
else
echo "OK"
endif
exit 0
****...続きを読む

Aベストアンサー

一発判定ではなくても、警告が出なければ良いんですよね?

***************************
set FILE = (`ls $DIR | grep *`)
if ( $#FILE != 0 ) then
echo "NG"
exit 1
else
echo "OK"
endif

exit 0
***************************

これなら警告でないはずです。

QUNIX Cシェルで実数の比較

UNIX Cシェルで実数の比較がしたいのですが、
うまくいきません
以下のような結果になります。
うまく判定するにはどうすればよいのでしょう

#!/bin/csh -f
set CONSIZE=-0.01
echo "CONSIZE = $CONSIZE"
@ CONSIZE = $CONSIZE
if( $CONSIZE < 0.0 )then
echo " 0以下;;; $CONSIZE"
exit
endif

実行
CONSIZE = -0.01
@: 数値形式が正しくありません。

Aベストアンサー

整数しか扱えない為、そのままでは比較することができないようです。

bc を利用してみてはいかがでしょうか?

#!/bin/csh -f
set CONSIZE=-0.01
echo "CONSIZE = $CONSIZE"
set x = `echo "scale=3;if( $CONSIZE < 0 ) 1" | bc`

if( $x == 1 )then
echo " 0以下;;; $CONSIZE"
exit
endif


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング