awk繰り返し{n}が機能していません


18

繰り返し記号{n}を使用して行を印刷しようとしていますが、機能していません。にとって。たとえば、長さが4文字のすべての行を印刷したい

 awk '/^.{4}$/' test_data

上記のコードはそれを印刷していません。繰り返し記号を使用できるように修正する方法は?私のような選択肢を知っているawk '/^....$/' test_dataし、awk 'length ==3 ' test_data


3
どのディストリビューションを使用していますか?どっち?
テルドン

1
$ awkの--version GNU Awkの3.1.7 $猫の/ etc / redhatのリリースのRed Hat Enterprise Linux Serverリリース6.7(サンティアゴ)
フォーエバー学習者

2
awk '/^.{4}+$/{print}' <<<$'foods\nbaarsz\nfooo' 正確に4文字に一致すると言います。また、自分で言ったように、 awk 'length($0) == 4' test_dataほとんどすべてのawkバージョンと互換性があります。
バレンティンバジラミ

4
やるawk --re-interval '/^.{4}$/' test_dataawk --posix '/^.{4}$/' test_data仕事?
スチールドライバー

スティールドライバーありがとうございます。これで問題が解決しました。賛成。再びありがとう:)
永遠に学習者

回答:


19

The GNU Awk User's Guide:Feature Historyによると、正規表現の範囲演算子のサポートはバージョン3.0で追加されましたが、最初は明示的なコマンドラインオプションが必要でした

新しいコマンドラインオプション:

  • 新しいコマンドラインオプション:
    • awkの元のバージョン7 Unixバージョン(V7 / SVR3.1を参照)で使用できない構成について警告する--lint-oldオプション。
    • BWK awkの-mオプション。(ブライアンは当時まだベル研究所にいました。)これは後に彼のawkとgawkの両方から削除されました。
    • 正規表現で間隔式を提供する--re-intervalオプション(正規表現演算子を参照)。
    • --compatのより良い名前として--traditionalオプションが追加されました(オプションを参照)。

ではgawk4.0、

間隔表現がデフォルトの正規表現の一部になりました

あなたが使用しているのでgawk3.xは、あなたが使用する必要があります

awk --re-interval '/^.{4}$/'

または

awk --posix '/^.{4}$/'

または(@StéphaneChazelasに感謝)ポータブルなソリューションが必要な場合は、

POSIXLY_CORRECT=anything awk '/^.{4}$/'

(以降--posixまたは--re-interval他の中のエラー原因となるawk実装が)。


あなたの時間と助けをありがとう、steeldriver。賛成票で受け入れられ、答えとして
永遠に学習者

4
POSIXLY_CORRECT=anything awk '/^.{4}/'移植可能なコードを作成する(--posixまたは--re-interval他のawk実装でエラーを引き起こす)ので、使用する方が適切です。
ステファンシャゼラス

こんにちは、StéphaneChazelas、コマンド$ POSIXLY_CORRECT = anything awk '/^.{4}/' test_dataを発行すると、すべての行が出力されました。それから、繰り返して最後のドルがないことに気づきました。ご意見ありがとうございます。コメントと解決策を支持します。申し訳ありませんが、繰り返した後の$の省略により、そもそもそれを誤解しました。
永遠に学習者

20

ERE(またはで使用される拡張正規表現)には最初はありませんでした。(またはで使用される)BREで最初に導入されましたが、後方移植性を損なうことのない構文を備えています。awkegrep{x,y}grepsed\{x,y\}

しかし、それがその{x,y}構文でEREに追加されたとき、foo{2}REが以前は異なる何かに一致していたため、後方への移植性を壊しました。

そのため、一部の実装ではそれを行わないことを選択しました。あなたはそれを見つけるでしょう/bin/awk/bin/nawkそして/bin/egrepSolarisではまだそれを尊重しません(/usr/xpg4/bin/awkまたはを使う必要があります/usr/xpg4/bin/grep -E)以下のための同じawkおよびnawkFreeBSD上で(に基づいて、ブライアン・カーニハンによって維持(中))。awkkawk

GNUawkでは、比較的最近まで(バージョン4.0)、POSIXLY_CORRECT=anything awk '/^.{4}$/'それを尊重するためにそれを呼び出す必要がありました。mawkまだそれを尊重しません

その演算子は構文糖だけであることに注意してください。たとえば、.{3,5}常に書くことができ....?.?ます(もちろん{3,5}、もっと読みやすく、同等のもの(foo.{5,9}bar){123,456}はもっと悪いでしょう)。


ステファン・シャゼラス、ありがとう。申し訳ありませんが、最初はあなたの答えを理解できませんでした。どうもありがとうございました。
永遠に学習者

6

これは、GNU awk(gawk)で期待どおりに機能します。

$ printf 'abcd\nabc\nabcde\n' | gawk '/^.{4}$/'
abcd

しかしmawk、POSIXに近い方が失敗しawk、AFAIKはUbuntuシステムのデフォルトです:

$ printf 'abcd\nabc\nabcde\n' | mawk '/^.{4}$/'
$ ## prints nothing

したがって、単純な解決策はのgawk代わりに使用することですawk{n}表記はPOSIX BRE(基本正規表現)構文の一部ではありません。それgrepがここでも失敗する理由です:

$ printf 'abcd\nabc\nabcde\n' | grep '^.{4}$'
$

ただし、これはERE(拡張正規表現)の一部です。

$ printf 'abcd\nabc\nabcde\n' | grep -E '^.{4}$'
abcd

どの正規表現フレーバーがmawkPOSIX awkで使用されているかわかりませんが、BREであると思いますStéphaneの回答によれば、彼らはEREの古いバージョンを使用しています。いずれにせよ、明らかにawkEREを実装していないバージョンを使用しているか、入力に実際に正確に4文字の行がありません。これは、表示されていない空白やグリフのユニコードなどが原因で発生する可能性があります。


こんにちは、4文字の行を印刷したいと思います。行の最初の4文字ではありません。たとえば、$はgrep -E「^ {4} $」TEST_DATAは、動作しますが、同じのawkで作業されていない
永遠学習者

@CppLearnerはい、それは私がここでやっていることです。どういう意味ですか?
テルドン

@ CppLearner、@ terdonのソリューションは、4文字の長さの行のみを印刷します。ただし、実際に行の長さにのみ関心がある場合はlength($0)、正規表現よりも効率的な方法を使用する必要があります。
スティーブンキット

こんにちは、steeldriverのソリューションは私が探していたものです。御時間ありがとうございます。こんにちはStephen Kitt、問題で述べたように、私はすでに長さを代替として使用しました、繰り返し正規表現{n}がsteeldriverのコメントから機能しない理由を知ることにもっと興味がありました--re-intervalまたは--posix。御時間ありがとうございます。
永遠に学習者

1
mawkPOSIX awkに実際には近くなく、BREを使用しません。EREを使用しますが、{x,y}演算子は使用しません。
ステファンシャゼラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.