2025, Oct 20 06:32

Windows UNC पाथ normalization: सही प्रीफ़िक्स डिटेक्शन और एकबारगी backslash escape

Windows पाथ्स को UNC extended-length में normalize कर Python कॉन्फ़िग के लिए सुरक्षित स्ट्रिंग लिटरल बनाएँ: सही UNC प्रीफ़िक्स पहचानें, एक बार backslash escape

जब आपको Windows पाथ्स को UNC extended-length प्रारूप में सामान्यीकृत करना हो और कॉन्फ़िगरेशन फ़ाइलों के लिए उन्हें स्ट्रिंग लिटरल के रूप में सीरियलाइज़ करना हो, तो दो बातें आसानी से गड़बड़ा जाती हैं: मौजूदा UNC प्रीफ़िक्स का पता लगाना और बैक्सलैश को दो बार एस्केप होने से बचाना। ये दोनों समस्याएँ तुरंत सामने आती हैं, खासकर जब इनपुट में पहले से \?\ प्रीफ़िक्स मौजूद हो या जब raw स्ट्रिंग्स शामिल हों।

समस्या का प्रदर्शन

नीचे एक न्यूनतम फ़ंक्शन है जो UNC प्रीफ़िक्स जोड़ने की कोशिश करता है और फिर लिटरल रूप में दिखाने के लिए बैक्सलैश को एस्केप करता है। यह मौजूदा प्रीफ़िक्स का पता लगाने की भी कोशिश करता है। इरादा ठीक है, नतीजा नहीं।

def to_unc_literal(pth: str) -> str:
    if pth.startswith(r"\\?\\"):
        base = pth
    else:
        base = r"\\?\\" + pth
    escaped_out = base.replace("\\", "\\\\")
    return escaped_out

यहाँ इनपुट और अपेक्षित लिटरल रूप दिया है। लक्ष्य यह सुनिश्चित करना है कि कंटेंट \?\ पाथ हो, और फिर उसे एस्केप किए हुए बैक्सलैश के साथ ऐसे रेंडर करना कि उसे कॉन्फ़िग मान में सुरक्षित रखा जा सके।

src_path = r"\\\\?\\C:\\Windows\\system32\\config\\systemprofile\\AppData\\Local\\temp\\p\\package_abc123\\p"
expected_literal = r"\\\\\\\\?\\\\C:\\\\Windows\\\\system32\\\\config\\\\systemprofile\\\\AppData\\\\Local\\\\temp\\\\p\\\\package_abc123\\\\p"
actual_literal = to_unc_literal(src_path)
print("Input:", repr(src_path))
print("Expected:", repr(expected_literal))
print("Actual:", repr(actual_literal))
print("Match:", actual_literal == expected_literal)

आउटपुट में जरूरत से कहीं ज़्यादा बैक्सलैश आ जाते हैं और प्रीफ़िक्स भी बिगड़ जाता है, जिससे साबित होता है कि डिटेक्शन और एस्केपिंग—दोनों की लॉजिक ग़लत है।

असल में क्या गलत हो रहा है

यहाँ दो अलग-अलग फँसाने वाले बिंदु हैं। पहला, कोई raw स्ट्रिंग एक अकेले बैक्सलैश पर खत्म नहीं हो सकती, इसलिए UNC प्रीफ़िक्स को r"\\?\" के रूप में लिख पाना संभव नहीं। इससे बचने के लिए प्रीफ़िक्स को r"\\?\\" (अंत में दो बैक्सलैश) लिख दिया गया। इससे लिटरल कंटेंट बदल जाता है और प्रीफ़िक्स डिटेक्शन टूट जाता है। दूसरा, फ़ंक्शन पाथ में बदलाव करने के बाद बिना सोचे-समझे हर बैक्सलैश को एस्केप कर देता है। अगर इनपुट में पहले से \?\ प्रीफ़िक्स है, तो यूँ ही बैक्सलैश बदलते रहने से एस्केपिंग दुहराई जाती है और स्ट्रिंग लिटरल फूला-फूला दिखने लगता है—यही त्रुटिपूर्ण नतीजे में दिखाई देता है।

संक्षेप में, raw-स्ट्रिंग वाले जुगाड़ की वजह से कोड गलत प्रीफ़िक्स पहचानता है, और फिर “पहले से एस्केप”, “raw UNC”, और “सामान्य पाथ”—इन मामलों को अलग न करने के कारण डबल-एस्केप कर देता है।

तर्क को सुरक्षित रूप से ठीक करना

इसे मज़बूत बनाने का सीधा तरीका है कि तीनों स्थितियों को साफ़-साफ़ संभाला जाए। अगर मान पहले से एस्केप किया हुआ UNC लिटरल है (लिटरल रूप में \\?\ से शुरू होता है), तो उसे जैसा है वैसा ही लौटा दें। अगर वह raw UNC पाथ है (\?\ से शुरू होता है), तो उसे एक बार एस्केप करें। वरना UNC प्रीफ़िक्स जोड़ें और एक बार एस्केप करें। साथ ही, प्रीफ़िक्स को normal स्ट्रिंग में लिखें ताकि अंत का बैक्सलैश सही ढंग से दर्शाया जाए।

def ensure_unc_literal(txt: str) -> str:
    # पहले से एस्केप किया हुआ UNC लिटरल (लिटरल रूप में \\?\...)
    if txt.startswith("\\\\\\\\?\\\\"):
        return txt
    # Raw UNC पाथ (\?\... वास्तविक कंटेंट के रूप में)
    elif txt.startswith("\\\\?\\"):
        return txt.replace("\\", "\\\\")
    # सामान्य पाथ: UNC प्रीफ़िक्स जोड़ें, फिर एक बार एस्केप करें
    else:
        prefix = "\\\\?\\"
        combined = prefix + txt
        return combined.replace("\\", "\\\\")

इससे एस्केपिंग idempotent (इडेम्पोटेंट) रहती है और सही UNC प्रीफ़िक्स उपयोग होता है। डिटेक्शन के लिए स्ट्रिंग्स ऐसे लिखी गई हैं कि वे रनटाइम पर Python स्ट्रिंग्स के वास्तविक कंटेंट से मेल खाएँ, न कि सिर्फ़ उनके डिस्प्ले रूप से।

यह क्यों महत्वपूर्ण है

यहाँ हुई गलतियाँ जल्दी-जल्दी बढ़ती जाती हैं। गलत UNC प्रीफ़िक्स शुरू से ही पाथ हैंडलिंग को बिगाड़ देता है। डबल-एस्केपिंग के कारण अपेक्षित लिटरल्स से तुलना करते समय मान पढ़ने में कठिन और असंगत हो जाते हैं, और इसका असर कॉन्फ़िग पार्सिंग, फ़ाइल एक्सेस और डिबगिंग तक पहुँच सकता है। इन तीन अवस्थाओं—पहले से एस्केप किया हुआ लिटरल, raw UNC, और सामान्य पाथ—को अलग रखकर आप दोहराव और सूक्ष्म बग्स से बच सकते हैं।

निष्कर्ष

UNC प्रीफ़िक्स के लिए normal स्ट्रिंग का उपयोग करें ताकि अंतिम बैक्सलैश सही तरह से दिखे। यह पहचानें कि पाथ पहले से एस्केप किया हुआ लिटरल है, raw UNC पाथ है, या सामान्य पाथ—और फिर एस्केपिंग ठीक एक बार लागू करें। इतना करने से न बिगड़े हुए प्रीफ़िक्स की समस्या रहेगी, न डबल-एस्केपिंग का जाल, और आप लगातार वही स्ट्रिंग लिटरल पाएँगे जो कॉन्फ़िगरेशन फ़ाइलों के लिए चाहिए।

यह लेख StackOverflow के प्रश्न पर आधारित है, जिसे tandem ने पूछा था, और tandem के उत्तर पर।