正規表現を使用して最後に特定の文字列なしでパターンを一致させる方法

正規表現を使用して最後に特定の文字列なしでパターンを一致させる方法

「POSIX BRE」または「POSIX ERE」正規表現を使用して文字列(行または単語)を一致させる方法いいえbakありますか?

最後に、ファイル名を持たls | egrep '<regex>'ないすべてのファイルを見つけることを作成したいと思います。bak

file1たとえば、、、、、file2_bakおよび3つのファイルがある場合、bak_file3正規表現はfile1andにのみ一致する必要がありますbak_file3(は一致しませんfile2_bak)。

を使用して実行できることを知っていますが、orオプションを使用せずに実行したいとls | grep -v 'bak$'思います。-vこれはPOSIX正規表現の理論的/学術的問題であるため、使用したくありません。grepegrep-v

bak最後にファイル名を一致させる方法は次のとおりです。

$ ls | egrep 'bak$'
file2_bak
$ 

上記の正規表現は、bak$最後に文字列があるすべての文字列と一致します。bakしかし、すべての文字列に一致する正規表現をどのように書くのですか?するいいえ持つ bak最後に?

答え1

ご使用の場合kshbashまたは拡張ワイルドカード有効にzshなったksh 球有効)ファイルグロービングモードを使用して、必要なものを取得できます.

ls -d -- !(*bak)

の場合、grep単純な解決策を得るには否定を使用してください-v

ls | grep -v 'bak$'

答え2

一般言語(「REと一致する可能性がある」など)は補完語の下に閉じられているため、可能ですが、実用的な目的にはあまり役に立ちません。条件付きで始まります。

最後の文字はANDですk。前の文字はANDです。a前の文字はANDです。b

(Python方式で作成しますs[-1]=='k' and s[-2]=='a' and s[-3]=='b') したがって、失敗した文字列は

not(s[-1]=='k' and s[-2]=='a' and s[-3]=='b')

つまり

not(s[-1]=='k') or not (s[-2]=='a' and s[-3]=='b'))

つまり

not(s[-1]=='k') or not(s[-2]=='a') or not(s[-3]=='b')

もちろん、DeMorganのルールを2回適用します。これは、文字列の長さが2以下の場合に特に当てはまります。したがって、おおよそ次のような結果が得られる。

grep '^$\|^.$\|^..$\|..[^k]$\|.[^a].$\|[^b]..$'

私はそれが型付け可能ですが、メンテナンスは不可能だと思います。

(理論的側面のメモ:通常、正規表現を決定論的有限自動デバイス(DFA)に変換し、最終状態を反転してから、新しいDFAをすべて明確に定義された正規表現に戻すことができます。多少退屈でエラーが発生する簡単なプロセスです)。

答え3

使用find:

find . -maxdepth 1 -type f ! -name "*bak"
  • .:現在の作業ディレクトリから検索するようにアサーションします。
  • -maxdepth 1:指定されたディレクトリの下の1つのレベルのみを取得するように指定します(つまり、現在の作業ディレクトリのみ)
  • -type f:ファイルのみ検索すると主張
  • ! -name "*bak":次に終わらないファイル名だけを検索すると主張します。bak

grep lsしかし、出力が必要な場合:

ls | grep -v 'bak$'
  • -v:与えられた正規表現と一致しない行だけを印刷します。

正規表現の分解:

  • bakbak文字列と一致します。
  • $: 行末と一致

否定的な振り返りを使用する場合も同様です(PCREs互換grepバージョンの場合)。

ls | grep -P '(?<!bak)$'
  • -PPCRE:s を使用して行を一致させます。

正規表現の分解:

  • (?<!bak): 前に文字列がない場合は、次のbakパターンのみが一致します。
  • $: 行末と一致

答え4

Perl拡張がある場合は、否定予測を使用できます。

grep -P '^.{0,2}$|^.*(?!bak)...$'

bakで終わらない行を一致させるために使用されます。

関連情報