জটিল স্ট্রিং সন্ধান এবং প্রতিস্থাপনের জন্য সেড ব্যবহার করা (পছন্দসই রেজেক্সের সাথে)


84

নিম্নলিখিত লিখিত সামগ্রীগুলির সাথে আমার একটি ফাইল রয়েছে:

<username><![CDATA[name]]></username>
<password><![CDATA[password]]></password>
<dbname><![CDATA[name]]></dbname>

এবং আমাকে এমন একটি স্ক্রিপ্ট তৈরি করতে হবে যা প্রথম লাইনের "নাম" কে "কিছু", দ্বিতীয় লাইনের "পাসওয়ার্ড" এবং "তৃতীয় লাইনের" নামকে "কিছু" আলাদা করে তুলবে। আমি এই ফাইলটিতে ঘটে যাওয়া ক্রমের উপর নির্ভর করতে পারি না, তাই আমি কেবল "নাম" এর প্রথম উপস্থিতিটিকে "কিছু" দিয়ে এবং "নাম" এর দ্বিতীয় ঘটনাটি "কিছু" দিয়ে প্রতিস্থাপন করতে পারি না। আমি সঠিক জিনিসটি খুঁজে পেয়েছি এবং প্রতিস্থাপন করছি তা নিশ্চিত করার জন্য আমাকে আশেপাশের স্ট্রিংগুলির অনুসন্ধান করতে হবে।

এখন পর্যন্ত আমি প্রথম "নাম" উপস্থিতিটি সন্ধান এবং প্রতিস্থাপনের জন্য এই আদেশটি চেষ্টা করেছি:

sed -i "s/<username><![CDATA[name]]><\/username>/something/g" file.xml

তবে এটি কাজ করছে না তাই আমি ভাবছি এর মধ্যে কয়েকটি চরিত্রের পালানোর দরকার হতে পারে ইত্যাদি etc.

আদর্শভাবে, আমি দুটি "ব্যবহারকারীর নাম" উপস্থিতিগুলির সাথে মেলে কেবলমাত্র "নাম" প্রতিস্থাপন করতে regex ব্যবহার করতে সক্ষম হতে চাই love এর মতো কিছু তবে সাথে sed:

<username>.+?(name).+?</username>

এবং বন্ধনীর সামগ্রীগুলিকে "কিছু" দিয়ে প্রতিস্থাপন করুন।

এটা কি সম্ভব?


2
কেবলমাত্র নোট করুন যে কোনও রেজিপ্সপ-ভিত্তিক সমাধান, চূড়ান্তভাবে অবদান না থাকলে, ইনপুট ফর্ম্যাটটি যে কোনও সময় পরিবর্তিত হওয়ার ঝুঁকিপূর্ণ হবে। এক্সএএমএল, এসজিএমএল বা ডেরিভেটস (যা এটি আমার কাছে দেখায়) এর সাথে ডিল করার জন্য রেগেক্সপস একটি দুর্বল পছন্দ।
একটি সিভিএন

অনুমোদিত! উদাহরণস্বরূপ XQuery ব্যবহার বিবেচনা করুন: w3schools.com/xquery/default.asp । এটি এক্সএমএল সামগ্রী পুনরুদ্ধার এবং পরিচালনা করার জন্য ডাব্লু 3 সি স্ট্যান্ডার্ড।
দীর্ঘ

উত্তর:


157
sed -i -E "s/(<username>.+)name(.+<\/username>)/\1something\2/" file.xml

এটি, আমি মনে করি, আপনি যা খুঁজছেন।

ব্যাখ্যা:

  • প্রথম অংশের প্রথম বন্ধনীগুলি গোষ্ঠীগুলি সংজ্ঞায়িত করে (আসলে স্ট্রিংগুলি) যা দ্বিতীয় অংশে পুনরায় ব্যবহার করা যেতে পারে
  • \1, \2ইত্যাদি ইত্যাদি প্রথম অংশে বন্দী আই-তম গ্রুপের উল্লেখ রয়েছে (নম্বরটি 1 দিয়ে শুরু হয়)
  • -Eপ্রসারিত নিয়মিত এক্সপ্রেশনগুলি সক্ষম করে (এর জন্য +এবং গ্রুপিংয়ের প্রয়োজন)।

20
-E বিকল্পের জন্য +1
স্ল্যাকমার্ট

4
এটি নামের সাথে একটি ব্যাকআপ ফাইলের পিছনে ছেড়ে যায় (original name) + "-E"
সার্জে বোর্শ

4
ওএসএক্সে আমি 'সেড' পেয়েছি: ":" এস / (<ব্যবহারকারীর নাম। +) নাম (। + ... ": the 1 আরই'তে সংজ্ঞায়িত হয়নি I আমি এই প্রশ্ন থেকে সঠিক উদাহরণটি একটি ফাইলে পেস্ট করেছি। এই ফাইলটির উত্তরটি থেকে আমি কমান্ডটি
চালিয়েছি Maybeএসএসএক্সের

1
সেডের gnu সংস্করণ "-E" প্যারামিটার সমর্থন করে তবে অফিসিয়াল নয়। এমনকি ম্যানপেজে এটি উল্লেখ করা হয়নি। আপনি যদি বর্ধিত রেজেক্স ব্যবহার করতে চান তবে আপনাকে তার পরিবর্তে "-r" পরামিতি ব্যবহার করতে হবে।
ইকেম ক্রুয়েজার

3
@deweydb মতে এই উত্তর , আপনি ব্যবহার করা উচিত \(এবং \)পরিবর্তে (এবং )
ঝাং বাজ

14
sed -e '/username/s/CDATA\[name\]/CDATA\[something\]/' \
-e '/password/s/CDATA\[password\]/CDATA\[somethingelse\]/' \
-e '/dbname/s/CDATA\[name\]/CDATA\[somethingdifferent\]/' file.txt

সেডের /username/আগে কেবল s'ইউজারনেম' স্ট্রিং যুক্ত লাইনে কাজ করতে বলা হয়েছে tells


1
মার্জিত, দক্ষ এবং কেস জন্য পুরোপুরি ফিট। +1
জর্জেট

6

যদি sedকোনও হার্ড প্রয়োজন না হয় তবে তার পরিবর্তে আরও উত্সর্গীকৃত সরঞ্জামটি ব্যবহার করুন।

যদি আপনার ফাইলটি বৈধ এক্সএমএল হয় (কেবল সেই 3 এক্সএমএল- দেখায় ট্যাগগুলি নয়) তবে আপনি এক্সএমএল স্টারলেট ব্যবহার করতে পারেন :

xml ed -P -O -L \
  -u '//username/text()' -v 'something' \
  -u '//password/text()' -v 'somethingelse' \
  -u '//dbname/text()' -v 'somethingdifferent' file.xml

উপরোক্ত পরিস্থিতিগুলিতেও কাজ করবে যা নিয়মিত প্রকাশের সাথে সমাধান করা কঠিন:

  • ট্যাগগুলির মানগুলি বর্তমান মানগুলি উল্লেখ না করে প্রতিস্থাপন করতে পারে।
  • মানগুলি কেবলমাত্র পালিয়ে যাওয়া এবং সিডিএটিএতে আবদ্ধ না হওয়া সত্ত্বেও প্রতিস্থাপন করতে পারে।
  • ট্যাগগুলির বৈশিষ্ট্য থাকলেও মানগুলি প্রতিস্থাপন করতে পারে।
  • যদি একই নামের সাথে একাধিক থাকে তবে সহজেই কেবল ট্যাগগুলির উপস্থিতি প্রতিস্থাপন করতে পারে।
  • পরিবর্তিত এক্সএমএল ইন্ডেন্ট করে ফর্ম্যাট করতে পারে।

উপরোক্ত সংক্ষিপ্ত প্রদর্শন:

bash-4.2$ cat file.xml
<sith>
<master>
<username><![CDATA[name]]></username>
</master>
<apprentice>
<username><![CDATA[name]]></username>
<password>password</password>
<dbname foo="bar"><![CDATA[name]]></dbname>
</apprentice>
</sith>

bash-4.2$ xml ed -O -u '//apprentice/username/text()' -v 'something' -u '//password/text()' -v 'somethingelse' -u '//dbname/text()' -v 'somethingdifferent' file.xml
<sith>
  <master>
    <username><![CDATA[name]]></username>
  </master>
  <apprentice>
    <username><![CDATA[something]]></username>
    <password>somethingelse</password>
    <dbname foo="bar"><![CDATA[somethingdifferent]]></dbname>
  </apprentice>
</sith>

3

আপনাকে কমান্ডের \[.*^$/নিয়মিত অভিব্যক্তির অংশে sএবং \&/প্রতিস্থাপন অংশে, পাশাপাশি নিউলাইনগুলি উদ্ধৃত করতে হবে । নিয়মিত প্রকাশটি একটি প্রাথমিক নিয়মিত প্রকাশ এবং অতিরিক্ত sকমান্ডের জন্য ডিলিমিটারটি উদ্ধৃত করা দরকার ।

উদ্ধৃতি না দেওয়ার জন্য আপনি আলাদা ডিলিমিটার চয়ন করতে পারেন /। পরিবর্তে আপনাকে সেই চরিত্রটি উদ্ধৃত করতে হবে, তবে সাধারণত ডিলিমিটার পরিবর্তন করার বিষয়টি হ'ল এমন একটি বাছাই করা হয় যা প্রতিস্থাপনের জন্য পাঠ্য বা প্রতিস্থাপন পাঠ্যের মধ্যে না ঘটে।

sed -e 's~<username><!\[CDATA\[name\]\]></username>~<username><![CDATA[something]]></username>~'

আপনি প্রতিস্থাপন পাঠ্যের কিছু অংশ পুনরাবৃত্তি এড়াতে গ্রুপগুলি ব্যবহার করতে পারেন এবং এই অংশগুলিতে পরিবর্তনের সামঞ্জস্য রাখতে পারেন।

sed -e 's~\(<username><!\[[A-Z]*\[\)name\(\]\]></username>\)~\1something\2~'

sed -e 's~\(<username>.*[^A-Za-z]\[\)name\([^A-Za-z].*</username>\)~\1something\2~'

3
$ sed -e '1s/name/something/2' \
      -e '3s/name/somethingdifferent/2' \
      -e 's/password/somethingelse/2' sample.xml

আপনি কেবল "s" এর আগের সংখ্যার মতো ঠিকানাগুলি ব্যবহার করতে পারেন যা লাইন নম্বরটি নির্দেশ করে।

এছাড়াও শেষ সংখ্যাটি sedপ্রথম ম্যাচের পরিবর্তে দ্বিতীয় ম্যাচটি প্রতিস্থাপন করতে বলে ।


1

"কিছু" শব্দের সাথে "নাম" শব্দটি প্রতিস্থাপনের জন্য, ব্যবহার করুন:

sed "s/\(<username><\!\[[A-Z]*\[\)name\]/\1something/g" file.xml

এটি নির্দিষ্ট শব্দের সমস্ত উপস্থিতি প্রতিস্থাপন করতে চলেছে।

এখনও পর্যন্ত সমস্ত স্ট্যান্ডার্ড আউটপুট আউটপুট করা হয়, আপনি ব্যবহার করতে পারেন:

sed "s/\(<username><\!\[[A-Z]*\[\)name\]/\1something/g" file.xml > anotherfile.xml

অন্য ফাইলে পরিবর্তনগুলি সংরক্ষণ করতে।


0
Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]...

    -r, --regexp-extended
             use extended regular expressions in the script.

সুতরাং একটি বৈশিষ্ট্য ফাইলে মান প্রতিস্থাপন

sed -i -r 's/MAIL\=(.+)/MAIL\=user@mymail.com/' etc/service.properties 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.