OpenBSDで動作しないawk正規表現の境界

OpenBSDで動作しないawk正規表現の境界

この awk 式はinet 34.45OpenBSD で期待どおりに印刷されます。

echo "inet 34.45" | awk '/inet [0-9]+\./ { print }'

ただし、+theをboundに置き換えると、{1,3}一致するものはありません。

echo "inet 34.45" | awk '/inet [0-9]{1,3}\./ { print }'

どちらの表現もLinuxのgawkでうまく動作します。 gawkのマニュアルページでは、awkは最初は間隔式をサポートしていませんでしたが、後でegrepとの整合性を維持するためにPOSIXに追加されたと言われています。 OpenBSD の awk のマニュアルページでは、そのような内容に言及するのではなく、通常のように範囲を指定する re_format のマニュアルページを引用します。

これはOpenBSD awkのバグですか、それとも文書化されていない制限ですか?

答え1

この制限は明確に文書化されています。

から:http://man.openbsd.org/awk.1#STANDARDS

基準

awkユーティリティはIEEE Std 1003.1-2008("POSIX.1")仕様に準拠していますが、awkは{n、m}パターンマッチングをサポートしていません。

答え2

OpenBSDの人々を保証することはできませんが、制限する理由があります。間隔表現OpenBSDと他のほとんどのawk実装はサポートされていません。可能なぜならひどい混乱、実装面。

gawkこれをサポートするGNU awk()を使用してテストケースから始めましょう。

time echo | gawk '/a{1,30000}/'
  # still going strong, after 5 minutes with the CPU at 100%
  # and eating up > 4G of memory

awkが使っているから本物正規表現(Perlの再帰/逆追跡スペースと時間無制限タイプではなくステートマシン/有限自動タイプ)、反復計算は次のようにのみ実行できます。静的反復正規表現サブ式コードから、必要なだけ何度も。

正規表現は実際にはa{1,4}コンパイル時にこのようなものに変わります。a(a(aa?)?)?これがどれほど迷惑なのか簡単にわかりますが、しかも非常に小さな反復:小さな反復にも/a{1,500}/0.5秒と多くのMBのメモリが必要です。


POSIX規制にもかかわらず、2020年4月現在、Debian 10(Buster)、OpenBSD 6.6、FreeBSD 12.1、Solaris 11のデフォルトのawkは間隔式をサポートしていません。/usr/bin/nawkDebian(使用中)mawkを除く他のすべてのレガシーnawkベース(「new awk」)。

GNU awkに加えて、インターバル式をサポートする他のawk実装には、busybox awkとNetBSDとMacOSのデフォルトawkが含まれます。

ノック(Knock)の子孫と言われる。ブッカー、「本当の奇妙な」)最近でも含むIMHOが間違いなくよく考えていない動きであるギャップ式をサポートします。

POSIXは歴史的に中断され、廃止されたawkの要件を強制しました。 1つの例は、0=="000"1(true)と評価する必要がある要件です。落ちる現在のバージョンの標準にはありますが、残念ながら/usr/xpg4/bin/awkSolarisに移植されて使用できなくなりました。

関連情報