Soru Dosya adının joker desenle eşleşip eşleşmediğini nasıl kontrol ederim?


Joker karakterim var, belki "* .txt" veya "POS". Dat ".

Ayrıca, o kalıpla karşılaştırmam gereken bellekte dosya adları listesi var.

Bunu nasıl yapılandıracağım, akılda kalıcı olarak IO.DirectoryInfo.GetFiles (desen) 'in kullandığı aynı semantiğe ihtiyacım var.

DÜZENLEME: Körü körüne bunu bir regex'e dönüştürmek işe yaramaz.


25
2018-03-16 20:26


Menşei


Şimdi bu soruyla karşılaşan herkes için, yıllar sonra, MSDN sosyal forumlarında GetFiles () yönteminin * ve? searchPattern parametresindeki joker karakterler. (En azından .Net 3.5, 4.0 ve 4.5) Directory.GetFiles (dize yolu, dize searchPattern) msdn.microsoft.com/en-us/library/wz42302f.aspx - jgerman


Cevaplar:


Senin için tam bir cevabım var% 95 gibi FindFiles(string).

Orada olmayan% 5, ikinci notta kısa isimler / uzun isimler davranışlarıdır. MSDN bu işlev için belgeler.

Bu davranışı hala almak istiyorsanız, giriş dizisinde sahip olduğunuz her dizenin kısa adının bir hesaplamasını tamamlamanız ve uzun adı veya kısa adı varsa uzun adı maçların koleksiyonuna eklemeniz gerekir. desenle eşleşir.

İşte kod:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace FindFilesRegEx
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] names = { "hello.t", "HelLo.tx", "HeLLo.txt", "HeLLo.txtsjfhs", "HeLLo.tx.sdj", "hAlLo20984.txt" };
            string[] matches;
            matches = FindFilesEmulator("hello.tx", names);
            matches = FindFilesEmulator("H*o*.???", names);
            matches = FindFilesEmulator("hello.txt", names);
            matches = FindFilesEmulator("lskfjd30", names);
        }

        public string[] FindFilesEmulator(string pattern, string[] names)
        {
            List<string> matches = new List<string>();
            Regex regex = FindFilesPatternToRegex.Convert(pattern);
            foreach (string s in names)
            {
                if (regex.IsMatch(s))
                {
                    matches.Add(s);
                }
            }
            return matches.ToArray();
        }

        internal static class FindFilesPatternToRegex
        {
            private static Regex HasQuestionMarkRegEx   = new Regex(@"\?", RegexOptions.Compiled);
            private static Regex IllegalCharactersRegex  = new Regex("[" + @"\/:<>|" + "\"]", RegexOptions.Compiled);
            private static Regex CatchExtentionRegex    = new Regex(@"^\s*.+\.([^\.]+)\s*$", RegexOptions.Compiled);
            private static string NonDotCharacters      = @"[^.]*";
            public static Regex Convert(string pattern)
            {
                if (pattern == null)
                {
                    throw new ArgumentNullException();
                }
                pattern = pattern.Trim();
                if (pattern.Length == 0)
                {
                    throw new ArgumentException("Pattern is empty.");
                }
                if(IllegalCharactersRegex.IsMatch(pattern))
                {
                    throw new ArgumentException("Pattern contains illegal characters.");
                }
                bool hasExtension = CatchExtentionRegex.IsMatch(pattern);
                bool matchExact = false;
                if (HasQuestionMarkRegEx.IsMatch(pattern))
                {
                    matchExact = true;
                }
                else if(hasExtension)
                {
                    matchExact = CatchExtentionRegex.Match(pattern).Groups[1].Length != 3;
                }
                string regexString = Regex.Escape(pattern);
                regexString = "^" + Regex.Replace(regexString, @"\\\*", ".*");
                regexString = Regex.Replace(regexString, @"\\\?", ".");
                if(!matchExact && hasExtension)
                {
                    regexString += NonDotCharacters;
                }
                regexString += "$";
                Regex regex = new Regex(regexString, RegexOptions.Compiled | RegexOptions.IgnoreCase);
                return regex;
            }
        }
    }
}

42
2017-12-07 09:22



Güzel, açıkça bunun üzerine biraz düşünmüşsün. - Jonathan Allen
Büyük kod parçası. HasAsteriskRegex değişkeni asla kullanılmaz. - Dor Rotman
@Dor Rotman, Teşekkürler ... Kodu uygun şekilde düzenledim. Muhtemelen başlangıçta desen doğruluğu için yıldız işaretini kontrol etmem ve daha sonra kullanılmayan RegEx'i kaldırmayı unutmam gerektiğini düşündüm. - sprite
* .txt benim düşünceme göre HeLLo.txtsjfhs ile eşleşir, kewljibin'in cevabı * .txt için düzgün çalışır, fakat büyük / küçük harfle ilgilenmez - Graham
@Graham Bir komut penceresi açın ve deneyin, sadece yaptım. dir .txt, hem "HeLLo.txt" hem de "HeLLo.txtsjfhs" değerini döndürür. Ayrıca, postandaki bağlantıya bakarsanız, MSDN'de DirectoryInfo.GetFiles Yönteminde tanımlanan davranışı göreceğiniz davranış budur. Orada uzun bir yorum var ve bazı örnekler. İşte buradalar: ".abc ".abc, .abcd, .abcde, .abcdef ve benzeri bir uzantıya sahip dosyaları döndürür.".abcd "sadece .abcd uzantılı bir dosya döndürür.".abcde "sadece .abcde uzantılı bir dosya döndürür." * .abcdef "sadece .abcdef uzantılı bir dosyayı döndürür. - sprite


Bunu basitçe yapabilirsiniz. Düzenli ifadelere ihtiyacınız yok.

using Microsoft.VisualBasic.CompilerServices;

if (Operators.LikeString("pos123.txt", "pos?23.*", CompareMethod.Text))
{
  Console.WriteLine("Filename matches pattern");
}

Veya VB.Net’de

If "pos123.txt" Like "pos?23.*" Then
  Console.WriteLine("Filename matches pattern")
End If

C # 'da bunu bir uzatma yöntemi ile simüle edebilirdiniz. Tam olarak VB gibi olmaz, ama ... çok havalı olurdu.


11
2017-09-27 00:01



Ya da ... VB.NET'te YAZILIYORSANIZ, like doğrudan operatör! 15 yıldır VB'yi yazıyorum ve hiç kullanmadım. like Şebeke. EĞER Operatörün var olduğunu hiç bilmiyordum, kullanma gereği duymadım. Şimdi kullanmayı düşünüyorum. - CrazyIvan1974
@ CrazyIvan1974, fikrini ekledim. Teşekkürler! - toddmo


Joker karakterleri normal bir ifadeye çevirebilirsiniz:

*.txt -> ^.+\.txt$

POS??.dat _> ^POS..\.dat$

Kullan Regex.Escape yöntem için karakter olmayan dizgiler halinde wildcars olmayan karakterlerden kaçma yöntemi (ör. dönüştürme) ".txt" için "\.txt").

Joker * çevirir .+, ve ? çevirir .

Dizenin başlangıcına uyacak şekilde ^ dizenin başlangıcına ve dizenin sonuna eşleşecek şekilde $ koyun.

Şimdi kullanabilirsiniz Regex.IsMatch Bir dosya adının desenle eşleşip eşleşmediğini kontrol etme yöntemi.


2
2018-03-16 20:35



-1 çünkü bu cevap sadece yanlış yanlıştır. Neredeyse iki örnek için çalışır, ancak regex'in büyük / küçük harfe duyarsız olduğundan emin olmanız gerekir. Ancak GetFiles davranışı oldukça karmaşıktır. Görmek msdn.microsoft.com/en-us/library/8he88b63.aspx detaylar için. - Jim Mischel
Deneme için teşekkürler, ama dediğim gibi GetFiles ile tam olarak eşleşmesi gerekiyor ve bu olmayacak. - Jonathan Allen
Peki, kısa dosya adlarının ne olduğunu bilmenin imkansız olduğu gibi, dosya isimleri listesiyle GetFiles ile aynı davranışı elde etmek mümkün değildir. - Guffa
Yanlışlık için -1. Üzgünüm ama Jim haklı. Vaka duyarsızlığı küçük problemdir, '*' ya da '?' İle ilgili olarak GetFiles (string) gibi davranmaz. desende karakterler. Yorumunda Jim posteri yazan MSDN makalesini okuyun. - sprite
kısa isimler hariç her şeye oldukça yakın olabilirsiniz. Bazı varsayımlar yaparsanız kısa ad davranışına bile yaklaşabilirsiniz. Örneğin, dosya adlarının girdideki sıralarına göre kısa adlara dönüştürülmesi gerektiğini varsayarak davranışı taklit edebilirsiniz. Örneğin. longfilename.txt ve longfileothername.txt dosyanız varsa, dizideki sıraya göre longfi ~ 1.txt ve longfi ~ 2.txt olacaktır. Eğer benim kod örneğime bakarsanız, kısa isimlerle birlikte bir çözüm verdim (ve neyin eksik olduğuna dair bir yorum). - sprite


Bir çeşit regex / glob gitmenin yolu, ama bazı incelikler var; sorunuz, aynı semantiği istediğinizi gösterir. IO.DirectoryInfo.GetFiles. Bu, 8.3 dosya uzun dosya adlarını ve benzerlerini içeren özel durumlar nedeniyle zor olabilir. Bütün hikaye açık MSDN.

Eğer tam bir davranışsal eşleşmeye ihtiyacınız yoksa, birkaç iyi SO sorusu vardır:

.NET'te eşleşen örüntü kalıbı
C # glob nasıl uygulanır


2
2018-03-16 20:40





Plz aşağıdaki kodu deneyin.

static void Main(string[] args)
    {
        string _wildCardPattern = "*.txt";

        List<string> _fileNames = new List<string>();
        _fileNames.Add("text_file.txt");
        _fileNames.Add("csv_file.csv");

        Console.WriteLine("\nFilenames that matches [{0}] pattern are : ", _wildCardPattern);
        foreach (string _fileName in _fileNames)
        {
            CustomWildCardPattern _patetrn = new CustomWildCardPattern(_wildCardPattern);
            if (_patetrn.IsMatch(_fileName))
            {
                Console.WriteLine("{0}", _fileName);
            }
        }

    }

public class CustomWildCardPattern : Regex
{
    public CustomWildCardPattern(string wildCardPattern)
        : base(WildcardPatternToRegex(wildCardPattern))
    {
    }

    public CustomWildCardPattern(string wildcardPattern, RegexOptions regexOptions)
        : base(WildcardPatternToRegex(wildcardPattern), regexOptions)
    {
    }

    private static string WildcardPatternToRegex(string wildcardPattern)
    {
        string patternWithWildcards = "^" + Regex.Escape(wildcardPattern).Replace("\\*", ".*");
        patternWithWildcards = patternWithWildcards.Replace("\\?", ".") + "$";
        return patternWithWildcards;
    }
}

0
2017-12-07 06:32



Bu, sprite'ın * .txt'deki yanıtından daha iyi çalışır, ancak bu, büyük ve küçük harfleri hesaba katmaz ve * .txt'yi sevmez mi? - Graham
Bu davranış, söz konusu olanla eşleşmiyor. DirectoryInfo.GetFiles yöntemini eşleştirmesi istendi. - sprite


Şimdi bu soruyla karşılaşan herkes için, yıllar sonra, MSDN sosyal forumlarında GetFiles () yönteminin * ve? searchPattern parametresindeki joker karakterler. (En azından .Net 3.5, 4.0 ve 4.5)

Directory.GetFiles(string path, string searchPattern)

http://msdn.microsoft.com/en-us/library/wz42302f.aspx


0
2018-04-01 18:25



Üzgünüm ama -1 soruya hiç cevap vermedin. - sprite
Artık bir sınırlama olmadığını söyleyen soruda belirtilen bir sınırlama cevabını verdim. Neden eski bir soruyu yeni bilgilerle güncelleyen, ancak güncellemeyi gönderirken asıl soruyu düzeltmek için yeterli itibara sahip olmayan birini cezalandırmak için kendi itibar puanlarınızı harcayabiliyorsunuz? - jgerman
Bu bir cevap olmadığı için, yazdıklarınız asıl soru hakkında bir yorum olmalıdır. Gönderen kişi veya moderatör daha sonra bir düzenleme yapabilir. Kişisel değil. Saygınlığımı "boşa harcamama" konusuna gelince, çok fazla bir şey umurumda değil, ben kimseyle rekabet halinde değilim. - sprite


Sadece bir Regex sınıfı kullanın. Bunu düşündüğünüz joker desenle başlatın ve eşleşip eşleşmediğini görmek için her dosya adını denetlemek için .IsMatch (filename) yöntemini kullanın.


-2
2018-03-16 20:29



Çoğu regex, OP'nin bahsettiği tipik kabuklardan farklı bir sözdizimi kullanır. Biliyorsun, durum bu .net olsun ya da olmasın. - rmeador
Joker karakterlerini yalnızca körü körüne düzenli ifadelere çeviremezsiniz. - Jonathan Allen
Aslında, joker desenleri normal ifadeye çeviremeyeceğinizi biliyordum. Sadece OP'nin, regex sınıfını kullanacağı zaman * .txt değerini eşdeğer regex'e çevirmesi gerektiğini anlayacağını düşünmüştüm. - Sanjay Sheth
Üzgünüm ama bunu reddetmek zorundaydım. Bu yanlış bitti. Joker desen biçimi, DirectoryInfo.GetFiles yönteminin MSDN belgelerinde anlatılanla aynı anlama sahip bir regex'e dönüştürülmez. - sprite


RegexOptions.IgnoreCase kullanımı düzeltecektir.

public class WildcardPattern : Regex {
    public WildcardPattern(string wildCardPattern)
        : base(ConvertPatternToRegex(wildCardPattern), RegexOptions.IgnoreCase) {
    }

    public WildcardPattern(string wildcardPattern, RegexOptions regexOptions)
        : base(ConvertPatternToRegex(wildcardPattern), regexOptions) {
    }

    private static string ConvertPatternToRegex(string wildcardPattern) {
        string patternWithWildcards = Regex.Escape(wildcardPattern).Replace("\\*", ".*");
        patternWithWildcards = string.Concat("^", patternWithWildcards.Replace("\\?", "."), "$");
        return patternWithWildcards;
    }
}

-2
2018-01-17 07:44



Bu soruya cevap veriyor mu? - FazoM