
[code]

    >>vi abc.log ↓
    10
    20
    30
    40
    50
    
[/code]

abc.log の内容は上記のようになっています。  
「40」「50」が含まれていた場合は「NG」、  
それ以外の時は「Ok」を結果として返す、  
シェルプログラムの作成方法（記述方法）を教えていただけないでしょうか？


CC BY-SA 3.0
2017-05-01T14:13:10.533
34406
2017-08-17T14:34:45.253
2017-05-01T21:03:15.073
19110
22902
question
csh
csh内の記述（if文の記載方法）


オイラも sakuro さんと同じ意見なので、そっちの答えなるものを bourne shell で書いてみる。  
誰かの参考になればということで思考過程なんかも記載してみる。

ファイルの中から `40` か `50` を探す、ということは `grep` を使えばよい、まではすぐ思いつく。  
今回やりたいのは OR 検索だけど `grep` で OR 検索ってどうするんだっけ？  
あたりからまず `man grep` してみる  
<https://linuxjm.osdn.jp/html/GNU_grep/man1/grep.1.html>

するとこの man page から下記のことがすべて読み取れる  
\- OR 検索には `-e` を複数回指定すればよい  
\- 終了コードは「見つかったとき 0 」「見つからなかったら 1 」  
\- 今回 `40` や `50` のエコーバックは要らないんだけど→ `-q` と `-s` で抑制できる

ということは単純に `if` を使えばよい。  
`if` の `then` 節は「成功」つまり終了コード `0` で起動されるわけだから

[code]

    $ if grep -s -q -e 40 -e 50 abc.log; then echo NG; else echo Ok; fi
    
[/code]

んであとは仕様に提示されていない考察漏れをまとめておくと上司に文句言われないで済む。

  * `450` とか `540` とか `5040` が含まれていたら `Ok` なんですか？それとも `NG` ？
  * 同様 `-40` や `-50` とかは？
  * いわゆる全角文字で `４０` とかはどないするんですか？
  * もし「いわゆる」全角を扱うなら encoding は何っすか？

あとは上司の指示/元発言者氏の補足待ちってことで。


CC BY-SA 3.0
2017-05-02T10:06:40.377
34418
2017-05-02T10:06:40.377
8589
34406
answer


別解。

各行を読み取り、その内容が `40` または `50` なら `ng` それ以外なら `OK` を各行ごとに表示、を bourne shell
で実装するものとする。

bourne shell において、標準入力から一行読むのは `read` であるとか、これを EOF まで繰り返すなら `while read`
であるとかは検索すればすぐヒットする。何度かシェルスクリプト書いたことがある人なら、文字列の一致比較は bourne shell の内蔵コマンド
`test` の演算子 `=` でできる、と知っているので、あとは `OR` をどうするのか？だけ。これも `man` から引くことができて `-o`
であることは容易に検索可能範囲。

[code]

    $ while read x; if [ $x = 40 -o $x = 50 ]; then echo NG; else echo Ok; fi; done
    
[/code]

までならそこそこすぐに書き下せる、んだと思う（これはダメな例）。

あとはこれにいろんな入力を与えてみると良い。シェルスクリプトのデバッグ慣れしている人なら「スペースを含む文字列」「 shell glob
文字を含む文字列」を与えるとエラーが出ることが多いことを承知しているだろう。ということで `read` の読む入力として `a b` とか `*`
を与えてみる。

[code]

    - bash: [: 引数が多すぎます
    
[/code]

うわ、やっぱり文句言われた。ということで何が問題なのかを知るには `echo` が便利。今デバッグしたいのは `test`
の式表記まわりだけなので、こんな感じにしてみる。

[code]

    $ while read x; echo [ $x = 40 -o $x = 50 ]; done
    a
    [ a = 40 -o a = 50 ]
    a b
    [ a b = 40 -o a b = 50 ]
    *
    [ a.out baz.c baz.h foo.cpp foo.h = 40 -o a.out baz.c baz.h foo.cpp foo.h = 50 ]
    $
    
[/code]

ああ `$x` が展開されちゃってるのね、と知ることが出来たら後は簡単 `$x` の不必要な展開を避けるにはダブルクオートで括ればよい。

[code]

    $ while read x; if [ "$x" = "40" -o "$x" = "50" ]; then echo NG; else echo Ok; fi; done
    
[/code]

左辺をダブルクオートするときは `"40"` や `"50"` のように右辺もダブルクオートしておくのがコツ。

あとは案件的にデリミタを受け付けるべき受け付けないべきから `read` にするか `read -r`
にするかどうかを決定し、最後にリダイレクトの明示をすれば事足りて

[code]

    $ cat abc.log | while read -r x; if [ "$x" = "40" -o "$x" = "50" ]; then echo NG; else echo Ok; fi; done
    
[/code]

あるいは

[code]

    $ while read -r x; if [ "$x" = "40" -o "$x" = "50" ]; then echo NG; else echo Ok; fi; done < abc.log
    
[/code]

のようにワンライナーになる。

もう一個の回答のほうで上げておいた考慮漏れ点は同じなのでその辺は省略。この回答と先の回答では `test` と `grep` の挙動の違いから `450`
等に対する結果が異なるのでその辺はご承知おきを。

オイラ的には `csh` スクリプトを書く気が全くないので、どうしても `csh` でなきゃならないのであればあとは誰かにお任せ。


CC BY-SA 3.0
2017-05-04T07:35:49.723
34455
2017-05-04T07:35:49.723
8589
34406
answer


Csh の場合、直前のコマンドの終了ステータスは `$status` で参照出来ます（tcsh では `$?` も使えるようです）。  
`if` 文では C言語風に数値の比較を行なえます。

[code]

    #!/bin/csh -f
    grep -qE '^(40|50)$' abc.log 
    
    if ($status == 0) then
        # 40 か 50 の行があった
        echo "NG"
    else
        # 40 か 50 の行はなかった
        echo "OK"
    endif
    
[/code]

また、`if` 文などの中で式が書ける場所では `{ }` で囲みコマンドの実行を行なえます。  
この部分の値はコマンドの終了ステータスが成功（0）ならば `1` に、そうでなければ `0` になります。  
よって、上の `grep` と `if` は、このように書く事も出来ます。

[code]

    if ({ grep -qE '^(40|50)$' abc.log }) then
    
[/code]

参考:  
[csh(1) - Linux man page](https://linux.die.net/man/1/csh)  
[Man page of TCSH - JM
Project](https://linuxjm.osdn.jp/html/tcsh/man1/tcsh.1.html)


CC BY-SA 3.0
2017-05-08T01:30:08.877
34532
2017-05-08T01:30:08.877
3054
34406
answer


皆様、教えて頂き有難う御座いました。  
abc.logには、「全角文字」や「マイナス符号」の文字列は記載されない仕様となっています。

ですので、「if grep -s -q -e 40 -e 50 abc.log; then echo NG; else echo Ok; fi」にて  
今回は解決させていただきました。

返信が遅くなり、大変失礼いたしました。


CC BY-SA 3.0
2017-08-17T14:34:45.253
37291
2017-08-17T14:34:45.253
22902
34406
answer