awk正規表現で演算と大文字と小文字を区別しませんか?

awk正規表現で演算と大文字と小文字を区別しませんか?

2つのテキストパターンを含むファイル名を一致させようとしていますが、一致プロセスでは大文字と小文字を無視する必要があります。次の正規表現は機能しません。

すべての正規表現および文字列操作で大文字と小文字を無視するように、awk変数 'IGNORECASE'をゼロ以外の値(で示されているようにinfo awk)に設定し、2つの正規表現を使用してすべてのファイルを印刷する論理的な「and」ジョブを構築します。 。

$ ls -R | awk 'IGNORECASE = 1;/bingo/ && /number/;'


テキストパターン "bingo"と "number"を一致させるためにプレビュー(2番目のプレビューは必要ないことを知っています)を使用する前に、データを小文字に変換してみました。ただし、awkはデフォルトで出力する必要がある出力を印刷しません。12

$ ls -R | awk 'tolower($0) ~ /(?=.*bingo)(?=.*number)/'

awkまたはregex構文のどの部分が間違っているか欠落しており、追加のパターンが同じ行に表示されている場合にのみ成功する大文字と小文字の独立した検索を実行する正しい方法は何ですか?

修正する:

ランニングで

$ ls -R | awk '/bingo/'

ファイル名に一致する文字列定数「bingo」が含まれていないawkため、出力内の各ファイルの行で一致が行われているようです。この場合、パイプから出力を受け取ったとき(つまりパイプを介して送信)と同じ動作をどのように取得できますか?ls -Rawkawkgrep

答え1

最初のスクリプトを書いてください。

awk 'IGNORECASE = 1;/bingo/ && /number/;'
  1. コメントで指摘したように、IGNORECASEはdorksに限定されています
  2. あなたのawkコードは次のとおりです。

    awk '(IGNORECASE = 1){print}; (/bingo/ && /number/){print}'
    

したがって、GNU awkでは大文字と小文字を区別せずに一致を実行しますが、他のawkではそうではありません。そして常に現在の行を印刷します(割り当ては真の条件IGNORECASE=1として評価されるため1)。次に、ビンゴと番号を含むすべての行を印刷します。第二。

2番目のスクリプトを書いてください。

awk 'tolower($0) ~ /(?=.*bingo)(?=.*number)/'

それは?=PCREツアーです。 awkはPCREではなくEREをサポートしているので、EREが実際に何を意味するのかを考慮する必要がありますが、それが何でも望む意味ではありません。

あなたの声明は次のとおりです。

awkは、ls -R出力の各ファイルの行に対して一致を実行しているようです。

なぜそう思うのかわかりませんが、そうではありません。

私はこれがGNU awkで欲しいものだと思います:

awk 'BEGIN{IGNORECASE=1}; /bingo/ && /number/'

または:

awk -v IGNORECASE=1 '/bingo/ && /number/'

いずれにせよ:

awk '{lc=tolower($0)}; (lc ~ /bingo/) && (lc ~ /number/)'

答え2

現在のディレクトリまたは文字列を含むディレクトリ内の名前を見つけるには、いずれのbingo場合でもnumberスループットの出力を渡さないでください。ls -Rawkfind

find . -iname '*bingo*' -iname '*number*'

この-iname述語は非標準ですが、通常は実装されており、指定されたワイルドカードパターンに対して現在確認されているファイル名と大文字と小文字を区別せずに一致します。

ファイル名を知りたい場合ただ、見つかったファイルのフルパス名の代わりに、次を使用します。

find . -iname '*bingo*' -iname '*number*' -exec basename {} \;

GNUでは、find次のことができます。

find . -iname '*bingo*' -iname '*number*' -printf '%f\n'

を使用するよりも高速ですbasename

2つの単語の順序が「bingo後ろにnumber」であることがわかっている場合は、両方のテストの代わりに-iname '*bingo*number*'withを使用してください。find-iname

探している単語の順序がこれであることがわかっている場合は、次のものを使用することもできbashます。

shopt -s globstar      # enable ** to match across / in pathnames
shopt -s nocaseglob    # enable case-insensitive globbing
shopt -s failglob      # error when a pattern does not match anything

printf '%s\n' **/*bingo*number*

パス名のファイル名部分を取得するには:

shopt -s globstar nocaseglob failglob

for name in **/*bingo*number*; do
    basename -- "$name"
done

またはGNUがあり、basename一致したくない場合数千ファイル数、

shopt -s globstar nocaseglob failglob

basename -a -- **/*bingo*number*

ここでは、-a各引数(複数の引数)のファイル名部分を表示するようにユーティリティに指示します。

Stéphaneは、コメント内の2つの部分文字列の順序を無視するためにbash拡張globbingパターンを使用できることを指摘しました。

!(!(*bingo*)|!(*number*))

これは、以下を除くすべての名前を一致させることによって行われます。欲しくない2つの文字列のうちの1つを含みます。だからあなたは得るでしょう

shopt -s globstar nocaseglob failglob
shopt -s extglob  # for extended globbing patterns in bash

for name in **/!(!(*bingo*)|!(*number*)); do
    basename -- "$name"
done

関連:

関連情報