この awk 式はinet 34.45
OpenBSD で期待どおりに印刷されます。
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/nawk
Debian(使用中)mawk
を除く他のすべてのレガシーnawkベース(「new awk」)。
GNU awkに加えて、インターバル式をサポートする他のawk実装には、busybox awkとNetBSDとMacOSのデフォルトawkが含まれます。
ノック(Knock)の子孫と言われる。ブッカー、「本当の奇妙な」)最近でも含むIMHOが間違いなくよく考えていない動きであるギャップ式をサポートします。
POSIXは歴史的に中断され、廃止されたawkの要件を強制しました。 1つの例は、0=="000"
1(true)と評価する必要がある要件です。落ちる現在のバージョンの標準にはありますが、残念ながら/usr/xpg4/bin/awk
Solarisに移植されて使用できなくなりました。