シェルスクリプトで役立つテキスト文字列のパターンマッチングの基礎Beginner's Guide(5/5 ページ)

» 2009年01月06日 14時46分 公開
[Peter Seebach,SourceForge.JP Magazine]
SourceForge.JP Magazine
前のページへ 1|2|3|4|5       

 一般的にパターンを用いたマッチングでは、最長マッチと呼ばれる一致判定が行われ、可能な限り広範な文字列とのマッチングが試みられる。しかし、アスタリスクのマッチ部に必要範囲以上のキャラクタが取り込まれた結果、当該パターン中のほかのコンポーネントによるマッチングが妨げられるというように、アスタリスクによる最長マッチに起因して目的とする文字列全体とのマッチングが行えなくなる可能性も存在するのだ。

 例えばパターンb*を用いた文字列bananaに対するマッチングでは*部のコンポーネントがananaというテキストに一致するが、このパターンをb*naに変更すると*部が一致するテキストはanaとなるというように、*はマッチングが可能な範囲内にて最大限のキャラクタを取り込もうとするのである。またキャラクタクラスなどそのほかのパターンコンポーネントについては、通常の文字であるリテラルキャラクタおよび特殊記号の1つである疑問符のマッチングが最優先され、その残りの部分に対してアスタリスクによるマッチングが行われるようになっている。

 こうしたシェルパターンに付随する制限の一部は、ユーザー側の工夫によって回避することも可能であり、例えば複数のアイテムを並べたリストをシェル内にて格納したければ、対象となるアイテム群をa,b,cのように区切り文字を挟んでつなげればいい。後記のサンプルコードは、こうしたリストの具体的な使用例である(このcaseステートメントでは、指定した文字列とパターンが一致した場合にのみ出力用のコードを実行する)。


list=orange,apple,banana
case $list in
*apple*)  echo "How do you like them apples?";;
esac
How do you like them apples?

 ただしこのサンプルスクリプトには、一致のチェックが厳密でないことに起因したバグが潜んでいる。具体的な問題点は、後記のような若干の変更を加えることで明確化するはずだ。


list=orange,crabapple,banana
case $list in
*apple*)  echo "How do you like them apples?";;
esac
How do you like them apples?

 これは先に触れたアスタリスクによる最長マッチに起因する問題であり、その対策としては、最長マッチの影響範囲と区切り記号のカンマの位置関係なども考えなくてはならない。一見すると、後記のようにパターン本体に区切り記号を追加するとうまく行きそうだが、今度はリストの両端に位置するアイテムには一致できなくなってしまう。


list=orange,apple,banana
case $list in
*,orange,*)  echo "The only fruit for which there is no Cockney slang.";;
esac
[no output]

 この問題の最終的な対処法としては、後記のようにリストの展開時に意図的に区切り記号を追加しておくことが考えられる。


list=orange,apple,banana
case ,$list, in
*,orange,*)  echo "The only fruit for which there is no Cockney slang.";;
esac
The only fruit for which there is no Cockney slang.

 こうして得られる$listの展開結果はカンマが両端に置かれた文字列となり、当該リストのアイテムすべてがカンマに挟まれた状態となるので、先のパターンによるマッチングは問題なく実行可能となる。

新しいことをはじめる前には「Beginner's Guide」で知識を得てみませんか?


前のページへ 1|2|3|4|5       

Copyright © 2010 OSDN Corporation, All Rights Reserved.

注目のテーマ