tuneoの日記: Pythonのglobモジュールでドはまり 4
日記 by
tuneo
UNIX風なワイルドカード展開を使おうと思ってドはまり。
メタ文字をエスケープできないじゃん!
カレントディレクトリに"[ほげほげ]てすと"というサブディレクトリを掘って、そこに置いたファイルa.txt, b.txt, ...の一覧をglob.glob()でゲットだぜ!ということをやりたいのだが。
>> from glob import glob
>> glob("[ほげほげ]てすと/*")
[]
glob.glob()では[]はワイルドカードになるから期待通りの結果が出ないのは当然だな。
……ということは、バックスラッシュでエスケープすればいいのかな?
>> glob(r"\[ほげほげ\]てすと/*")
[]
……ダメだ。お手上げorz。
os.popen()で/bin/lsシェルを呼ぶのは、なるべくならやりたくない。Windowsで動かなくなるしな。
Pythonで巧いこと済ませる方法はあるだろうか?
追記:ソースを追っかけたりしたんだが、よくよくfnmatch.pyを読んでみたらコメントに
There is no way to quote meta-characters.
と書いてあった。メタ文字をクォートする方法は無いのかorz。
walk (スコア:0)
勘ですが (スコア:1)
"\\\[ほげほげ\\\]"
ではいかがでしょう?
" と " で囲まれている範囲のエスケープで
は
になります。これを glob パーサーが解釈して
になる。
fjの教祖様
Re:勘ですが (スコア:1)
Pythonの文字列定数の処理においては
・"\\"→"\"
・"\["→"\["
ですから、"\\\["は"\\["にしかなりません。というわけで、うまくいかんです。
# そういうバックスラッシュ置換を抑止するために「r"..."」って書いてあるんですけどね。
globモジュールからソースを追っかけてみたところ
という流れになってました。fnmatch.translate()でパターンを正規表現に変換して、re.match()を使ってマッチさせているというカラクリです。さて、今回使ったパターンが実際にどんな正規表現に変換されているのかというと。
……なんか色々違うorz。"\["と"\]"の処理もさることながら、[]の外側のひらがな一つ一つをバックスラッシュでエスケープしてるあたりもかなり胡散臭い(問題は無いんだけど、そうする必要もない)。当然、マッチさせてみてもスカです。
正しくマッチする正規表現はr"\[ほげほげ\]てすと/.*.txt$"です。
ちなみにokkyさんご提案のパターンだとこうなります。
結局のところ正しい正規表現に変換できないfnmatch.translate()が原因ですね。
しかし、このモジュールって昔っから(10年以上前から)あるんだけど、誰も気づかなかったのか……。
Re:勘ですが (スコア:1)
> 正しくマッチする正規表現はr"\[ほげほげ\]てすと/.*.txt$"です。
ピリオドをバックスラッシュでエスケープしてないから、これは嘘ですね。
ホントの正解はr"\[ほげほげ\]てすと/.*\.txt$"です。
……自己レスだけどID。