আশেপাশের অক্ষরগুলি না ছাপিয়ে 'সেড' এর সাথে মিলে যাওয়া একটি রেজেক্স বের করা


24

সমস্ত 'সেড' ডাক্তারকে সেখানে বাইরে:

আপনি একটি রেখায় মেলে এমন একটি নিয়মিত ভাব প্রকাশ করতে কীভাবে 'সেড' পেতে পারেন?

অন্য কথায়, আমি কেবল স্ট্রিংটি নিয়মিত অভিব্যক্তির সাথে সামঞ্জস্য করা লাইনটি থেকে থাকা সমস্ত মিলহীন অক্ষরের সাথে সরে যেতে চাই।

আমি নীচের মত ব্যাক-রেফারেন্স বৈশিষ্ট্যটি ব্যবহার করার চেষ্টা করেছি

regular expression to be isolated 
         gets `inserted` 
              here     
               |
               v  
 sed -n 's/.*\( \).*/\1/p 

এটি কিছু মত প্রকাশের জন্য কাজ করে

 sed -n 's/.*\(CONFIG_[a-zA-Z0-9_]*\).*/\1/p 

যা 'কনফিগ_ ....' দিয়ে শুরু করে সমস্ত ম্যাক্রো নাম ঝরঝরে করে বের করে দেয় (কিছু '* .এইচ' ফাইলে পাওয়া যায়) এবং সেগুলি লাইন দিয়ে সমস্ত লাইন প্রিন্ট করে

          CONFIG_AT91_GPIO
          CONFIG_DRIVER_AT91EMAC
                   .
                   .   
          CONFIG_USB_ATMEL
          CONFIG_USB_OHCI_NEW
                   .
                 e.t.c. 

কিন্তু উপরের মতো কিছু ভেঙে যায়

  sed -n 's/.*\([0-9][0-9]*\).*/\1/p 

এটি সর্বদা একক অঙ্কগুলি প্রদান করে

                 7
                 9
                 .
                 .  
                 6

পরিবর্তে যেমন একটি সংক্ষিপ্ত নম্বর ক্ষেত্র নিষ্কাশন।

              8908078
              89670890  
                 .
                 .  
                 .
               23019   
                 .
               e.t.c.  

PS: আমি কীভাবে 'সেড' এ এটি অর্জন করা হয়েছে সে সম্পর্কে প্রতিক্রিয়া জানাতে আমি কৃতজ্ঞ হব। আমি জানি এই কিভাবে করতে হবে সঙ্গে ', grep' এবং 'awk' আমি খুঁজে বের করতে চাই যদি আমার - যদিও সীমিত - 'sed' বোঝার এতে গর্ত আছে এবং যদি সেখানে এই 'sed' আমি যা যা করতে উপায়
আছে কেবল উপেক্ষা করা।

উত্তর:


22

যখন একটি রেজিপ্সে গ্রুপ থাকে, তখন এর বিরুদ্ধে স্ট্রিংয়ের মিলের একাধিক উপায় থাকতে পারে: গোষ্ঠীগুলির সাথে রিজেক্সপগুলি অস্পষ্ট। উদাহরণস্বরূপ, regexp ^.*\([0-9][0-9]*\)$এবং স্ট্রিং বিবেচনা করুন a12। দুটি সম্ভাবনা রয়েছে:

  • aবিপক্ষে .*এবং 2বিপক্ষে ম্যাচ [0-9]*; 1দ্বারা মেলানো হয় [0-9]
  • a1বিপক্ষে ম্যাচ .*এবং এর বিরুদ্ধে খালি স্ট্রিং [0-9]*; 2দ্বারা মেলানো হয় [0-9]

শেড, অন্য সমস্ত রেজিএক্সএক্স সরঞ্জামগুলির মতো, সবচেয়ে দীর্ঘতম ম্যাচের নিয়মটি প্রয়োগ করে: এটি প্রথমে যতটা সম্ভব তার স্ট্রিংয়ের সাথে প্রথম ভেরিয়েবল-দৈর্ঘ্যের অংশটি মেলানোর চেষ্টা করে। এটি যদি রেজিএক্সপি বাকি অংশের সাথে বাকী স্ট্রিংয়ের সাথে কোনও মিল খুঁজে পায়, ঠিক আছে। অন্যথায়, সেড প্রথম পরিবর্তনশীল-দৈর্ঘ্যের অংশের জন্য পরবর্তী দীর্ঘতম ম্যাচটি চেষ্টা করে এবং আবার চেষ্টা করে।

এখানে, সবচেয়ে দীর্ঘতম স্ট্রিংয়ের সাথে ম্যাচটি প্রথম a1বিপক্ষে .*, সুতরাং গ্রুপটি কেবল মিলছে 2। আপনি যদি গোষ্ঠীটি শুরু করতে চান তবে কিছু রিজেক্সপ ইঞ্জিন আপনাকে .*কম লোভী করতে দেয় তবে সেডের এমন বৈশিষ্ট্য নেই। সুতরাং আপনার কিছু অতিরিক্ত অ্যাঙ্কর দিয়ে অস্পষ্টতা সরিয়ে ফেলতে হবে । উল্লেখ করুন যে শীর্ষস্থানীয় অঙ্কটি দিয়ে .*শেষ হতে পারে না, যাতে গোষ্ঠীর প্রথম সংখ্যাটি প্রথম সম্ভাব্য ম্যাচ হয়।

  • অঙ্কের গোষ্ঠীটি যদি লাইনের শুরুতে নাও পারে:

    sed -n 's/^.*[^0-9]\([0-9][0-9]*\).*/\1/p'
    
  • যদি অঙ্কগুলির গোষ্ঠীটি লাইনের শুরুতে হতে পারে এবং আপনার সেড \?অপারেটরটিকে partsচ্ছিক অংশগুলির জন্য সমর্থন করে :

    sed -n 's/^\(.*[^0-9]\)\?\([0-9][0-9]*\).*/\1/p'
    
  • যদি সংখ্যার গোষ্ঠীটি লাইনের শুরুতে হতে পারে তবে স্ট্যান্ডার্ড রিজেক্সপ কনস্ট্রাক্টসের সাথে লেগে থাকে:

    sed -n -e 's/^.*[^0-9]\([0-9][0-9]*\).*/\1/p' -e t -e 's/^\([0-9][0-9]*\).*/\1/p'
    

যাইহোক, এটি একই দীর্ঘতম দীর্ঘতম ম্যাচের নিয়ম যা [0-9]*পরবর্তীকালের পরিবর্তে প্রথমটির পরে অঙ্কগুলির সাথে মেলে .*

মনে রাখবেন যে যদি কোনও লাইনে ডিজিটের একাধিক ক্রম থাকে তবে আপনার প্রোগ্রামটি সর্বকালের দীর্ঘতম ম্যাচের নিয়মের কারণে প্রাথমিকটিতে প্রয়োগ হওয়ার কারণে, সর্বদা অঙ্কের শেষ ক্রমটি বের করবে .*। আপনি যদি অঙ্কগুলির প্রথম ক্রমটি বের করতে চান তবে আপনাকে অবশ্যই উল্লেখ করতে হবে যে এর আগে যা আসে তা অ-অঙ্কের ক্রম।

sed -n 's/^[^0-9]*\([0-9][0-9]*\).*$/\1/p'

আরও সাধারণভাবে, একটি রেজিএক্সএক্সের প্রথম ম্যাচটি এক্সট্রাক্ট করার জন্য আপনাকে সেই রেজিএক্সপ্যাকের অস্বীকৃতি গণনা করতে হবে। যদিও এটি সর্বদা তাত্ত্বিকভাবে সম্ভব, আপনি যে রেজিপেক্সটি উপেক্ষা করছেন তার আকারের সাথে প্রত্যাখ্যানের আকারটি তাত্পর্যপূর্ণভাবে বৃদ্ধি পায়, তাই এটি প্রায়শই অবৈধ।

আপনার অন্যান্য উদাহরণ বিবেচনা করুন:

sed -n 's/.*\(CONFIG_[a-zA-Z0-9_]*\).*/\1/p'

এই উদাহরণটি একই সমস্যাটি প্রদর্শন করে, তবে আপনি এটি সাধারণ ইনপুটগুলিতে দেখেন না। আপনি যদি এটি খাওয়ান hello CONFIG_FOO_CONFIG_BAR, তবে উপরের কমান্ডটি প্রিন্ট করে CONFIG_BAR, না CONFIG_FOO_CONFIG_BAR

সেডের সাথে প্রথম ম্যাচটি প্রিন্ট করার একটি উপায় রয়েছে তবে এটি কিছুটা জটিল:

sed -n -e 's/\(CONFIG_[a-zA-Z0-9_]*\).*/\n\1/' -e T -e 's/^.*\n//' -e p

(ধরে নিলাম আপনার শেড প্রতিস্থাপন পাঠ্যে \nএকটি নতুন লাইন বোঝায় mean s) এটি কাজ করে কারণ সেড রেজিএক্সপেক্সের প্রথম দিকের ম্যাচটি সন্ধান করে, এবং আমরা CONFIG_…কিছুটা আগে কী মিলবে তা চেষ্টা করি না । যেহেতু লাইনের ভিতরে কোনও নিউলাইন নেই, তাই আমরা এটিকে অস্থায়ী চিহ্নিতকারী হিসাবে ব্যবহার করতে পারি। Tকমান্ড ছেড়ে দিতে হবে যদি পূর্ববর্তী বলেছেন sকমান্ড মেলেনি।

আপনি যখন কিছু উপায়ে কীভাবে করতে পারবেন তা যখন বুঝতে পারছেন না, ততক্ষণে ফিরে যান। নিম্নলিখিত কমান্ডটি একটি রেইগ এক্সপের সবচেয়ে দীর্ঘতম ম্যাচ মুদ্রণ করে:

awk 'match($0, /[0-9]+/) {print substr($0, RSTART, RLENGTH)}'

এবং যদি আপনি এটি সহজ রাখার মত বোধ করেন তবে পার্ল ব্যবহার করুন।

perl -l -ne '/[0-9]+/ && print $&'       # first match
perl -l -ne '/^.*([0-9]+)/ && print $1'  # last match

22

যদিও তা না হলেও এর sedজন্য প্রায়শই একটি বিষয় অবহেলিত হয় grep -oযা আমার মতে এই কাজের জন্য আরও ভাল সরঞ্জাম।

উদাহরণস্বরূপ, আপনি যদি CONFIG_কার্নেল কনফিগারেশন থেকে সমস্ত পরামিতি পেতে চান তবে আপনি এটি ব্যবহার করবেন:

# grep -Eo 'CONFIG_[A-Z0-9_]+' config
CONFIG_64BIT
CONFIG_X86_64
CONFIG_X86
CONFIG_INSTRUCTION_DECODER
CONFIG_OUTPUT_FORMAT

আপনি যদি সংখ্যার সংলগ্ন ক্রমগুলি পেতে চান:

$ grep -Eo '[0-9]+' foo

7
sed '/\n/P;//!s/[0-9]\{1,\}/\n&\n/;D'

... এটি কোনও ডাব্লু / ডাব্লু আউট করবে, যদিও nডান হাতের প্রতিস্থাপন ক্ষেত্রে আপনার জায়গায় আক্ষরিক নতুন লাইনের প্রয়োজন হতে পারে । এবং, যাইহোক, .*CONFIGজিনিসটি কেবল তখনই কাজ করবে যদি লাইনে কেবল একটি ম্যাচ থাকে - এটি অন্যথায় সর্বদা সর্বশেষটি পেত।

আপনি দেখতে পারেন এই কিভাবে এটি কাজ করে একটি বিবরণ জন্য, কিন্তু এই একটি পৃথক লাইন অনেক বার হিসাবে শুধুমাত্র ম্যাচ প্রিন্ট হবে যেমন একটি লাইনে দেখা দেয়।

আপনি একই কৌশলটি [num]কোনও লাইনে উপস্থিতি পেতে ব্যবহার করতে পারেন । উদাহরণস্বরূপ, আপনি যদি কনফিগ ম্যাচটি প্রিন্ট করতে চান তবে তা যদি কোনও লাইনে এটি তৃতীয় হয়:

sed '/\n/P;//d;s/CONFIG[[:alnum:]]*/\n&\n/3;D'

... যদিও এটি ধরে নিয়েছে যে CONFIGস্ট্রিংগুলিকে প্রতিটি ঘটনার জন্য কমপক্ষে একটি অ-অক্ষরীয় অক্ষর দ্বারা পৃথক করা হয়েছে।

আমি মনে করি - সংখ্যাটির জন্য - এটিও কাজ করবে:

sed -n 's/[^0-9]\{1,\}/\n/g;s/\n*\(.*[0-9]\).*/\1/p

... ডান হাত সম্পর্কে আগের মত একই সাবধানে \n। এটি প্রথমটির চেয়ে আরও দ্রুততর হবে তবে সাধারণভাবে স্পষ্টতই প্রয়োগ করা যায় না।

কনফিগ জিনিসটির জন্য আপনি P;...;Dউপরের লুপটি আপনার প্যাটার্ন দিয়ে ব্যবহার করতে পারেন বা আপনি এটি করতে পারেন:

sed -n 's/[^C]*\(CONFIG[[:alnum:]]*\)\{0,1\}C\{0,1\}/\1\n/g;s/\(\n\)*/\1/g;/C/s/.$//p'

... যা সামান্য আরও জড়িত এবং সঠিকভাবে sedউল্লেখের অগ্রাধিকার অর্ডার দিয়ে কাজ করে । এটি একই সাথে সমস্ত কনফিগ ম্যাচগুলিকে এক লাইনে বিচ্ছিন্ন করে - যদিও এটি আগের মতো একই ধারণা করে তোলে - প্রতিটি সিএনএফজি ম্যাচ কমপক্ষে একটি অ-অক্ষরীয় অক্ষর দ্বারা পৃথক হবে। জিএনইউ দিয়ে sedআপনি এটি লিখতে পারেন:

sed -En 's/[^C]*(CONFIG\w*)?C?/\1\n/g;s/(\n)*/\1/g;/C/s/.$//p'
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.