

以下のファイルから、egrepでサーバ名を抜きだそうとしました。

[code]

    ===test.txt===
    tokyoAAsv01
    tokyoBBsv01
    tokyoCCsv01
    tokyoAAsv02
    tokyoBBsv02
    =====end====
    
    cat /tmp/test.txt | egrep '*sv01|*sv02'
    
[/code]

これは上手くいくのですが、

[code]

    cat /tmp/test.txt | egrep 'tokyo*sv01|tokyo*sv02'
    
[/code]

とやると失敗します。  
さらに test.txt から、AA,CCのつく行だけを抜き出したい場合、どのように書いたら良いでしょうか。

よろしくお願いします。

追記：  
すみません、最後の、AA、CCのつく行だけを〜のところなのですが、説明不足でした。

[code]

    ===test.txt===
    tokyoAAsv01
    tokyoBBsv01
    tokyoCCsv01
    tokyoAAsv02
    tokyoBBsv02
    osakaAAsv01
    osakaBBsv01
    osakaCCsv01
    =====end====
    
[/code]

のように、他の拠点のサーバも混ざっており、AA、BBのパターンも10以上あります。  
そこで、`tokyo` の `AA,CC,FF,HH` だけ、のような書き方をしたいのですが、  
その場合、OR条件を入れ子にすることは難しいのでしょうか？  
以下のようにやってみたのですが上手くいきませんでした。

[code]

    cat /tmp/test.txt | egrep 'tokyo|AA|CC|FF|HH|sv01|tokyo|AA|CC|FF|HH|sv02'
    
[/code]

後出しで申し訳ございません。


CC BY-SA 3.0
2015-11-16T07:24:18.560
18881
2015-11-16T09:10:45.937
2015-11-16T08:36:18.930
9807
question
grep
egrepでワイルドカードの入ったOR検索


`*` は「直前の１文字の０回以上のくりかえし」なので `tokyo*sv01` は  
\- 文字列 `toky` があって、  
\- その直後に `o` が０回以上出現して  
\- さらに `sv01` がある  
にマッチします。マッチパターンを例示すると  
`tokysv01` `tokyosv01` `tokyoosv01` `tokyooooooooooosv01`

欲しいマッチが `tokyo` のあと任意の文字があって `sv01` が引き続く、ならば

[code]

    egrep 'tokyo.*sv01' /tmp/test.txt
    
[/code]

でしょう。 `.` は「任意の１文字」です。

`AA` `CC` のほうはもっと簡単というか、まるっきりそのままのような気がします。  
`egrep 'AA|CC' /tmp/test.txt` ってことだと思いますが・・・

元質問の編集を受けて追記

`tokyo` かつ (`AA` または `BB` ) かつ `sv01` ってことですよね？ `OR` ではなくて `AND` 。  
可読性をあげるため、オイラなら `grep` をパイプでつなぐ、かな。

[code]

    egrep 'tokyo' /tmp/test.txt | egrep 'AA|BB' | egrep 'sv01'
    
[/code]


CC BY-SA 3.0
2015-11-16T07:55:14.940
18887
2015-11-16T08:56:10.693
2015-11-16T08:56:10.693
8589
8589
18881
answer


>
[code]

>     cat /tmp/test.txt | egrep 'tokyo*sv01|tokyo*sv02'
>  
[/code]

おそらく、`tokyo` の後に `sv01` または `sv02` が来る行を検索したいのだと思います。`*` は直前の正規表現 (単なる文字も含む)
の0回以上の繰り返しですから、`tokyo*sv01` は `tokysv01`, `tokyooooooosv01` などにはマッチしますが
`tokyoAAsv01` などにはマッチしません。

任意の文字列を表すには、`.` (任意の1文字) の後に `*` を置いて次のようにします。

[code]

     egrep 'tokyo.*sv01|tokyo.*sv02' /tmp/test.txt
    
[/code]

または

[code]

     egrep 'tokyo.*sv0[12]' /tmp/test.txt
    
[/code]

> さらに test.txt から、AA,CCのつく行だけを抜き出したい場合、どのように書いたら良いでしょうか。

つぎのように、`|` で繋げると、OR の意味になります。

[code]

    egrep 'AA|CC' /tmp/test.txt
    
[/code]

**追記**

> `tokyo` の `AA`, `CC`, `FF`, `HH` だけ、のような書き方をしたい

`(` ... `)` で括ることでグループ化することができます。

[code]

    egrep 'tokyo(AA|CC|FF|HH)sv0[12]' /tmp/test.txt
    
[/code]


CC BY-SA 3.0
2015-11-16T07:57:14.413
18888
2015-11-16T08:53:12.667
2015-11-16T08:53:12.667
76
76
18881
answer


既に回答が付いていますので補足など少し。

> **Repetition**
>
> A regular expression may be followed by one of several repetition operators:
>
> * The **preceding item** will be matched zero or more times.

最初の正規表現についてですが、

[code]

    cat /tmp/test.txt | egrep '*sv01|*sv02'
    
[/code]

`*sv01|*sv02` の中の `*` における `preceding item`
は空文字列("")になります。空文字列を何回繰り返しても空文字列ですので、結局は、

[code]

    cat /tmp/test.txt | egrep 'sv01|sv02'
    
[/code]

と同じことになります。

**追記**

> そこで、tokyo の AA,CC,FF,HH だけ、のような書き方をしたいのですが、

同じ文字の繰り返し(2回)、ということであれば以下の様な書き方も。

[code]

    cat /tmp/test.txt | egrep 'tokyo([ACFH])\1'
    
[/code]

※ 実際のデータの内容は違うとは思いますが、まぁ、この様な書き方もありますよ、ということで。


CC BY-SA 3.0
2015-11-16T08:05:40.207
18889
2015-11-16T09:10:45.937
2015-11-16T09:10:45.937
18881
answer