単二電池

最近シェルスクリプトの勉強をはじめまして、一度自分で作ってみようと思い

行頭が数字の行を表示するシェルスクリプトを書いてみました。

が、うまく出来ません。

表示させたいファイルは字幕ファイルの始めの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

A 回答 (5件)

とりあえず問題点とその理由を書き出しますと。


if の後の [ ] はtestコマンドのエイリアスなのですが、
testコマンドでは、数値としての比較あるいは文字そのものかの比較しかできないので、
ワイルドカードや、正規表現は使えません。
$ hoge=012
$ test $hoge = 012; echo $? ならば返値は0ですが、
$ test $hoge = 0*; echo $? みたいなことはできず返値は1となって不一致となります。
なので、ワイルドカードや正規表現を利用して判断基準を作りたいならば、
case構文を利用するか、あるいはgrepなどを利用する必要があります。
また、仮にtestコマンドでワイルドカードや正規表現が使えたとしても、
[0-9][0-9]では、目的のものには引っかかりません。
正規表現で 1改行 2改行 などをマッチさせたいならば、
$ grep '^[0-9]*$'なんてしないとかかりません。
次に、これは別に間違いではないのですが、
ファイルを<や<<でインプットとかヒアドキュメントすると、
それが最後にかかれるために、複雑になってくると、どれがどこを読んでいるのか分かりにくくなります。
必要ならばファイルは素直にcatの引数として渡したほうが無難でしょう。
以上を踏まえきちんといらないところを省いてやれば、
#!/bin/sh
grep '^[0-9]*$' hoge.txt
と、かけます。
この場合、ifもtestもヒアドキュメントもいらず、コマンド一回ですむスクリプトかどうか疑わしいもので十分なわけです。
    • good
    • 0
この回答へのお礼

回答ありがとうございます


>ファイルを<や<<でインプットとかヒアドキュメントすると、
それが最後にかかれるために、複雑になってくると、どれがどこを読んでいるのか分かりにくくなります。

今後の参考にします


>以上を踏まえきちんといらないところを省いてやれば、
#!/bin/sh
grep '^[0-9]*$' hoge.txt
と、かけます。
この場合、ifもtestもヒアドキュメントもいらず、コマンド一回ですむスクリプトかどうか疑わしいもので十分なわけです。

そうですね、スクリプトにする必要もありませんね(笑)

お礼日時:2011/09/06 23:45

修正です



> [ (test)コマンドで eq は「文字列が等しい」です。
→ eqなどという演算子は用意されていません。 = で「文字列が等しい」 -eqで「数値(整数)が等しい」です。
パターンマッチでは無いのは同様です。

> grep '^[0-9][0-9]*' $1
→ 数字だけの行なら grep '^[0-9][0-9]*$' $1 でした。
ただ、既に指摘のあるように、「数字だけの行」なのか「数字で始まる行」なのかがはっきりしないので、どちらが正しいかわかりません
    • good
    • 0
この回答へのお礼

スミマセン

-eq でした(使う必要もないけど・・・)

お礼日時:2011/09/06 23:35

ちょっと確認:


「行頭が数字の行」には
00:00:03,600 --> 00:00:07,195
なども含まれるはずなんだけど, 「望む結果」に入っていないのはなぜ?
    • good
    • 0
この回答へのお礼

すみません、説明不足でしたね。

正確には「数字のみの行」でした。

お礼日時:2011/09/06 23:37

シェルでプログラムするのも良いですが、この場合は#1のgrepやSED、Perlなどのコマンドを活用するとより簡単に探せます。



SEDは、下記のような1行で終わりです(動作確認していないですが ^ ^;)。
$ SED -e '/^[0-9]/p'

意味
・/^xxx/は、「//」が探すパターンを指定、「/^xxx/」はxxxで始まるパターンという意味
・/[0-9]/は、0、1、2・・・、9を表現する正規表現


SEDの説明
http://itpro.nikkeibp.co.jp/article/COLUMN/20060 …

SEDは、古くからあるツールですが、ご質問のような作業には最適なツールと思います。
    • good
    • 0
この回答へのお礼

回答ありがとうございます

sedコマンドは行を削除するだけのコマンドだと思ってました

お礼日時:2011/09/06 23:36

> if [ "$Line" eq [0-9][0-9] ]



ここでエラーになったりしませんか?
・[ (test)コマンドで eq は「文字列が等しい」です。完全一致です。正規表現などのパターンマッチではありません
・[0-9][0-9] こういうものは、まず、ファイル名に展開されます。ls *.txt とかやったときには、「lsが *.txt にマッチするファイルを探す」のではなく、「シェルが*.txtにマッチするファイル名に展開してからlsを実行」します。実際に実行されれうのは、例えば ls a.txt b.txt c.txt とかになります。
この場合、数字2桁のファイル名がなければエラーになるか、そのまま[0-9][0-9]という文字列になります(設定による)

パターンマッチさせたければ、case文を使うとか、grep等のコマンドを使うとかになります。

もっとも、grepを使うなら

grep '^[0-9][0-9]*' $1

の1行で終わりですけど。


あと、while read line みたいなのは最後の手段って思っておいた方がいいですよ。大抵は 各種コマンド(grep,sed..)とパイプで効率よく記述できますから
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

>[ (test)コマンドで eq は「文字列が等しい」です。完全一致です。正規表現などのパターンマッチではありません

なるほど、勉強になります。



>もっとも、grepを使うなら

 grep '^[0-9][0-9]*' $1

 の1行で終わりですけど

そうします。スクリプトにする必要もありませんでしたね(笑)



>あと、while read line みたいなのは最後の手段って思っておいた方がいいですよ

自分は、それが最高の手段だと思ってました、最後だったのですね(汗)

お礼日時:2011/09/06 23:34

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