পাইথনের একটি স্ট্রিংয়ে পালানোর ক্রমগুলি প্রক্রিয়া করুন Process


112

কখনও কখনও যখন আমি কোনও ফাইল বা ব্যবহারকারীর কাছ থেকে ইনপুট পাই, আমি এতে পালাবার ক্রম সহ একটি স্ট্রিং পাই। আমি পাইথন যেভাবে স্ট্রিং লিটারেলগুলিতে এস্কেপ সিকোয়েন্সগুলি প্রসেস করে সেভাবেই এস্কেপ সিকোয়েন্সগুলি প্রক্রিয়া করতে চাই ।

উদাহরণস্বরূপ, আসুন যাক myStringহিসাবে সংজ্ঞায়িত করা হয়:

>>> myString = "spam\\neggs"
>>> print(myString)
spam\neggs

আমি একটি ফাংশন চাই (আমি এটি কল করব process) যা এটি করে:

>>> print(process(myString))
spam
eggs

এটি গুরুত্বপূর্ণ যে ফাংশনটি পাইথনের সমস্ত পালানোর ক্রমগুলি প্রক্রিয়া করতে পারে (উপরের লিঙ্কের একটি টেবিলের তালিকাভুক্ত)।

পাইথনের কি এটি করার জন্য কোনও ফাংশন আছে?


1
হুঁ, কীভাবে আপনি 'spam'+"eggs"+'''some'''+"""more"""প্রক্রিয়াজাত স্ট্রিং যুক্ত আশা করতে পারেন ?
নাস বানভ

@ নাস বনভ এটি একটি ভাল পরীক্ষা। স্ট্রিংটিতে কোনও পালানোর ক্রম নেই, তাই প্রক্রিয়াজাতকরণের পরে এটি ঠিক একই হওয়া উচিত। myString = "'spam'+\"eggs\"+'''some'''+\"\"\"more\"\"\"", print(bytes(myString, "utf-8").decode("unicode_escape"))কাজ বলে মনে হচ্ছে।
dln385

5
এই প্রশ্নের বেশিরভাগ উত্তরের গুরুতর সমস্যা রয়েছে। ইউনিকোড না ভেঙে পাইথনে পালানোর সিকোয়েন্সগুলিকে সম্মান করার কোনও স্ট্যান্ডার্ড উপায় নেই বলে মনে হয়। @ স্প্রেয়ার পোস্ট করা উত্তরটি হ'ল গ্রাকোর পক্ষে আমি গ্রহণ করেছি কারণ এটি এখনও পর্যন্ত সমস্ত পরিচিত কেসগুলি পরিচালনা করে।
অপালালা

উত্তর:


138

সঠিক জিনিসটি হ'ল স্ট্রিংটি ডিকোড করার জন্য 'স্ট্রিং-পলায়ন' কোডটি ব্যবহার করুন।

>>> myString = "spam\\neggs"
>>> decoded_string = bytes(myString, "utf-8").decode("unicode_escape") # python3 
>>> decoded_string = myString.decode('string_escape') # python2
>>> print(decoded_string)
spam
eggs

এএসটি বা ইভাল ব্যবহার করবেন না। স্ট্রিং কোডেকগুলি ব্যবহার করা অনেক বেশি নিরাপদ।


3
হাত নীচে, সেরা সমাধান! বিটিডব্লিউ, ডকস দ্বারা এটি "স্ট্রিং_সেসকেপ" (আন্ডারস্কোর সহ) হওয়া উচিত তবে কোনও কারণে 'স্ট্রিং এস্কেপ', 'স্ট্রিং @ পলায়ন "এবং কী ন্যূনতম বিন্যাসের কোনও কিছু গ্রহণ করে ... মূলত'string\W+escape'
নাস বানভ ২ov

2
@ নাস বনভ ডকুমেন্টেশনগুলি সম্পর্কে একটি সামান্য উল্লেখ করেছে :Notice that spelling alternatives that only differ in case or use a hyphen instead of an underscore are also valid aliases; therefore, e.g. 'utf-8' is a valid alias for the 'utf_8' codec.
dln385

30
এই সমাধানটি যথেষ্ট ভাল নয় কারণ এটি সেই ক্ষেত্রে পরিচালনা করে না যেখানে মূল স্ট্রিংয়ে বৈধ ইউনিকোড অক্ষর রয়েছে। যদি আপনি চেষ্টা করেন: >>> print("juancarlo\\tañez".encode('utf-8').decode('unicode_escape')) আপনি পেয়েছেন: juancarlo añez
আপালালা

2
@ অ্যাপালালার সাথে একমত: এটি যথেষ্ট ভাল নয়। পাইথন 2 এবং 3 তে কাজ করে এমন একটি সম্পূর্ণ সমাধানের জন্য নীচে রসিপারের উত্তরটি দেখুন!
খ্রিস্টান আইচিংগার

2
যেহেতু latin1ধরে নেওয়া হয়েছে unicode_escape, এনকোড / ডিকোড বিটটি আবার করুন, উদাহরণস্বরূপs.encode('utf-8').decode('unicode_escape').encode('latin1').decode('utf8')
মেটাটোস্টারে

121

unicode_escape সাধারণভাবে কাজ করে না

দেখা যাচ্ছে যে সমাধান string_escapeবা unicode_escapeসমাধানটি সাধারণভাবে কাজ করে না - বিশেষত, এটি প্রকৃত ইউনিকোডের উপস্থিতিতে কাজ করে না।

আপনি যদি নিশ্চিত হন যে প্রতিটি অ-এএসসিআইআই চরিত্র পালাতে পারে (এবং মনে রাখবেন, প্রথম 128 টি অক্ষরের বাইরে যে কোনও কিছু অ-এসসিআইআই নয়) unicode_escapeআপনার জন্য সঠিক কাজ করবে। তবে যদি আপনার স্ট্রিংটিতে ইতিমধ্যে কোনও আক্ষরিক অ-এসসিআইআই অক্ষর থাকে তবে জিনিসগুলি ভুল হয়ে যাবে।

unicode_escapeবাইটসকে ইউনিকোড পাঠ্যে রূপান্তর করতে মৌলিকভাবে ডিজাইন করা হয়েছে। তবে অনেক জায়গায় - উদাহরণস্বরূপ, পাইথন উত্স কোড - উত্স ডেটা ইতিমধ্যে ইউনিকোড পাঠ্য।

এটি সঠিকভাবে কাজ করার একমাত্র উপায় হ'ল যদি আপনি প্রথমে পাঠ্যকে বাইটে এনকোড করেন। ইউটিএফ -8 হ'ল সমস্ত পাঠ্যের জন্য বুদ্ধিমান এনকোডিং, তাই কাজ করা উচিত, তাই না?

নিম্নলিখিত উদাহরণগুলি পাইথন 3 এ রয়েছে, যাতে স্ট্রিং লিটারেলগুলি আরও পরিষ্কার হয় তবে পাইথন 2 এবং 3 উভয় ক্ষেত্রে একই সমস্যাটি কিছুটা পৃথক প্রকাশের সাথে বিদ্যমান।

>>> s = 'naïve \\t test'
>>> print(s.encode('utf-8').decode('unicode_escape'))
naïve   test

ঠিক আছে, এটা ভুল।

পাঠ্যগুলিতে পাঠ্যকে ডিকোড করে কোডেকগুলি ব্যবহার করার নতুন প্রস্তাবিত উপায়টি হ'ল codecs.decodeসরাসরি কল করা। এটা কি সাহায্য করে?

>>> import codecs
>>> print(codecs.decode(s, 'unicode_escape'))
naïve   test

একেবারেই না. (এছাড়াও, উপরেরটি পাইথন ২-এ একটি ইউনিকোড ইরর))

unicode_escapeকোডেক এর নাম সত্ত্বেও, সক্রিয় আউট অনুমান করা যে সমস্ত নন- ASCII বাইট ল্যাটিন -1 (ISO-8859-1-) এনকোডিং এ আছে। সুতরাং আপনি এটি এইভাবে করতে হবে:

>>> print(s.encode('latin-1').decode('unicode_escape'))
naïve    test

তবে তা ভয়ানক। এটি আপনাকে 256 ল্যাটিন -1 বর্ণগুলিতে সীমাবদ্ধ করে, যেন ইউনিকোড কখনও আবিষ্কার করা যায় নি!

>>> print('Ernő \\t Rubik'.encode('latin-1').decode('unicode_escape'))
UnicodeEncodeError: 'latin-1' codec can't encode character '\u0151'
in position 3: ordinal not in range(256)

সমস্যা সমাধানের জন্য একটি নিয়মিত ভাব প্রকাশ করা

(আশ্চর্যের বিষয়, আমাদের এখন দুটি সমস্যা নেই))

আমাদের যা করা দরকার তা হ'ল কেবলমাত্র সেই unicode_escapeজিনিসগুলিতে ডিকোডার প্রয়োগ করা যা আমরা নিশ্চিত হ'ল ASCII পাঠ্য। বিশেষত, আমরা কেবল এটি বৈধ পাইথন এস্কেপ সিকোয়েন্সগুলিতে প্রয়োগ করতে নিশ্চিত করতে পারি, যা ASCII পাঠ্য হওয়ার গ্যারান্টিযুক্ত।

পরিকল্পনাটি হ'ল, আমরা একটি নিয়মিত এক্সপ্রেশন ব্যবহার করে পালানোর সিকোয়েন্সগুলি খুঁজে পাব এবং re.subতাদের অচিহ্নবিহীন মান দিয়ে তাদের প্রতিস্থাপনের জন্য যুক্তি হিসাবে একটি ফাংশন ব্যবহার করব।

import re
import codecs

ESCAPE_SEQUENCE_RE = re.compile(r'''
    ( \\U........      # 8-digit hex escapes
    | \\u....          # 4-digit hex escapes
    | \\x..            # 2-digit hex escapes
    | \\[0-7]{1,3}     # Octal escapes
    | \\N\{[^}]+\}     # Unicode characters by name
    | \\[\\'"abfnrtv]  # Single-character escapes
    )''', re.UNICODE | re.VERBOSE)

def decode_escapes(s):
    def decode_match(match):
        return codecs.decode(match.group(0), 'unicode-escape')

    return ESCAPE_SEQUENCE_RE.sub(decode_match, s)

এবং এটি দিয়ে:

>>> print(decode_escapes('Ernő \\t Rubik'))
Ernő     Rubik

2
আমাদের এর মতো আরও বেশি প্রকারের উত্তর দরকার। ধন্যবাদ।
v.oddou

এটি কি os.sepআদৌ কাজ করে ? আমি patt = '^' + self.prefix + os.sep ; name = sub(decode_escapes(patt), '', name)এটি করার চেষ্টা করছি: এবং এটি কাজ করছে না। সেমিকোলন একটি নতুন লাইনের জায়গায় রয়েছে।
পিওরফেরেট

@ পিয়ারফেরেট আপনি যা জিজ্ঞাসা করছেন তা আমি সত্যিই নিশ্চিত নই তবে আপনি সম্ভবত স্ট্রিংগুলিতে এটি চালাবেন না যেখানে উইন্ডোজ ফাইল পাথের মতো ব্যাকস্ল্যাশটির আলাদা অর্থ রয়েছে। (এটি কি আপনার os.sep?) যদি আপনার উইন্ডোজ ডিরেক্টরিগুলির নামগুলিতে পিছনে সিকোয়েন্সগুলি থাকে তবে পরিস্থিতিটি অনেকটা অপ্রত্যাশিত।
আরএসপিয়ার

পালানোর ক্রমটি তাদের মধ্যে পালাতে পারে না, তবে আমি একটি '
বোগাসে

যে আমাকে বলে যে আপনি একটি ব্যাকস্ল্যাশ সঙ্গে কিছু অন্যান্য রেগুলার এক্সপ্রেশন শেষ হয়েছে: stackoverflow.com/questions/4427174/...
rspeer

33

অজগর 3 এর জন্য প্রকৃত সঠিক এবং সুবিধাজনক উত্তর:

>>> import codecs
>>> myString = "spam\\neggs"
>>> print(codecs.escape_decode(bytes(myString, "utf-8"))[0].decode("utf-8"))
spam
eggs
>>> myString = "naïve \\t test"
>>> print(codecs.escape_decode(bytes(myString, "utf-8"))[0].decode("utf-8"))
naïve    test

সম্পর্কিত বিশদ codecs.escape_decode:

  • codecs.escape_decode বাইট-টু-বাইটস ডিকোডার
  • codecs.escape_decodeঅ্যাস্কি এস্কেপ সিকোয়েন্সগুলি ডিকোড করে যেমন: b"\\n"-> b"\n", b"\\xce"-> b"\xce"
  • codecs.escape_decode বাইট অবজেক্টের এনকোডিংয়ের বিষয়ে যত্ন নেই বা জানতে হবে না, তবে পালানো বাইটের এনকোডিংটি অবজেক্টের বাকী এনকোডিংয়ের সাথে মেলে।

পটভূমি:


এটিই আসল উত্তর (: খুব খারাপ এটি একটি দুর্বল-নথিভুক্ত ফাংশনের উপর নির্ভর করে
jwd

5
আপনি যে \xইউটিএফ -8 বাইটের পালাচ্ছেন সেখানকার উত্তরগুলির উত্তর এটি । তবে এটি বাইটগুলিকে বাইটগুলি ডিকোড করার কারণে, এটি ASCII নন ইউনিকোডের অক্ষর যেমন \uপলায়নের মতো পলায়ন ডিকোড করে - এবং করতে পারে না ।
আরএসপিয়ার

কেবল একটি এফওয়াইআই, এই ফাংশনটি প্রযুক্তিগতভাবে সর্বজনীন নয়। দেখতে bugs.python.org/issue30588
Hack5

8

ast.literal_evalফাংশন বন্ধ আসে, কিন্তু এটা স্ট্রিং প্রথমে সঠিকভাবে উদ্ধৃত করা আশা হবে।

অবশ্যই ব্যাকস্ল্যাশ প্যাথনের ব্যাখ্যার পাল্টে যায় তার উপর নির্ভর করে স্ট্রিংটি কীভাবে উদ্ধৃত করা হয় ( ""বনাম r""বনাম u"", ট্রিপল কোটস ইত্যাদি) যাতে আপনি উপযুক্ত ইনপুটগুলিতে ব্যবহারকারীর ইনপুটটি মোড়তে এবং পাস করতে চাইতে পারেন literal_eval। এটিকে উদ্ধৃতিতে মোড়ানো literal_evalকোনও সংখ্যা, টিপল, অভিধান ইত্যাদি ফিরিয়ে দেওয়া থেকেও বিরত থাকবে will

আপনি স্ট্রিংয়ের চারপাশে মোড়ানোর জন্য ব্যবহারকারী যে ধরণের অব্যক্ত উদ্ধৃতিটি টাইপ করেন সেগুলি এখনও জটিল হয়ে উঠতে পারে।


আমি দেখি. এই যেমন আপনি বলতে সম্ভাব্য বিপজ্জনক মনে করা হয়: myString = "\"\ndoBadStuff()\n\"", print(ast.literal_eval('"' + myString + '"'))রান কোডে চেষ্টা বলে মনে হয়। এর ast.literal_evalচেয়ে আলাদা / নিরাপদ কীভাবে eval?
dln385

5
@ dln385: literal_evalকখনও কোড চালায় না। ডকুমেন্টেশন থেকে, "এটি নিজেরাই মূল্যবোধগুলি বিশ্লেষণ না করে অবিশ্বস্ত উত্স থেকে পাইথন এক্সপ্রেশন যুক্ত স্ট্রিংগুলি নিরাপদে মূল্যায়নের জন্য ব্যবহার করা যেতে পারে।"
গ্রেগ হিউগিল

2

এটি এটি করার একটি খারাপ উপায়, তবে পালানো অক্টালগুলি একটি স্ট্রিং আর্গুমেন্টে পাস করার ব্যাখ্যা দেওয়ার চেষ্টা করার সময় এটি আমার পক্ষে কাজ করেছিল।

input_string = eval('b"' + sys.argv[1] + '"')

এটি উল্লেখ করার মতো যে এখানে eval এবং ast.literal_eval (ইওলাল আরও নিরাপদ হওয়ার উপায়) এর মধ্যে পার্থক্য রয়েছে। দেখুন পাইথন এর Eval ব্যবহার () বনাম ast.literal_eval ()?


0

নীচে কোডটির জন্য should n কাজ করা উচিত স্ট্রিংটিতে প্রদর্শিত হওয়া প্রয়োজন।

import string

our_str = 'The String is \\n, \\n and \\n!'
new_str = string.replace(our_str, '/\\n', '/\n', 1)
print(new_str)

1
এটি লিখিত হিসাবে কাজ করে না (ফরোয়ার্ড স্ল্যাশগুলি replaceকিছুই করতে পারে না), বন্যভাবে পুরানো এপিআই ব্যবহার করে ( stringএই ধরণের মডিউল ফাংশনগুলি পাইথন ২.০ হিসাবে অবহিত করা হয়, strপদ্ধতিগুলি দ্বারা প্রতিস্থাপন করা হয়েছে , এবং পাইথন 3 এ সম্পূর্ণভাবে গেছে), এবং কেবল সাধারণ পালানোর প্রক্রিয়াজাতকরণ নয়, একটি একক নিউলাইন প্রতিস্থাপনের নির্দিষ্ট ক্ষেত্রে পরিচালনা করে।
শ্যাডোর্যাঞ্জার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.