কী মিলছে কেবল মুদ্রণের জন্য কীভাবে সেড, অজ, বা গাওক ব্যবহার করবেন?


101

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

তবে আমার ক্ষেত্রে আমার একটি নিয়মিত প্রকাশ রয়েছে যা আমি একটি নির্দিষ্ট মান বের করতে কোনও পাঠ্য ফাইলের বিরুদ্ধে চালাতে চাই। আমি অনুসন্ধান এবং প্রতিস্থাপন করতে চাই না। এটি বাশ থেকে আহ্বান করা হচ্ছে। আসুন একটি উদাহরণ ব্যবহার করুন:

নিয়মিত প্রকাশের উদাহরণ:

.*abc([0-9]+)xyz.*

উদাহরণ ইনপুট ফাইল:

a
b
c
abc12345xyz
a
b
c

এই শোনার মতোই সহজ, আমি ঠিক কীভাবে সেড / অ্যাওক / গাউককে কল করব তা বুঝতে পারি না। আমি যা করতে আশা করছিলাম তা আমার বাশ স্ক্রিপ্টের মধ্যে থেকে:

myvalue=$( sed <...something...> input.txt )

আমি যে জিনিসগুলির চেষ্টা করেছি সেগুলির মধ্যে রয়েছে:

sed -e 's/.*([0-9]).*/\\1/g' example.txt # extracts the entire input file
sed -n 's/.*([0-9]).*/\\1/g' example.txt # extracts nothing

10
বাহ ... লোকেরা এই প্রশ্নটি নীচে ভোট দিয়েছেন -১? এটা কি আসলেই কোনও প্রশ্নের অনুপযুক্ত?
স্টাফেন

এটি পুরোপুরি উপযুক্ত বলে মনে হচ্ছে, রেজেেক্স এবং সেড / অ্যাজকের মতো শক্তিশালী কমান্ড লাইন ইউটিলিটিগুলি বা ভিআই, ইমাকস বা টেকো এর মতো কোনও সম্পাদক ব্যবহার করা কেবল কিছু 'অ্যাপ্লিকেশন ব্যবহার না করে প্রোগ্রামিংয়ের মতো হতে পারে। আইএমও এটি এসইউর চেয়ে বেশি এসইউ সম্পর্কিত।
Dereleased

সম্ভবত এটি ভোট দেওয়া হয়েছিল কারণ প্রাথমিক আকারে এটি এর কিছু প্রয়োজনীয়তার স্পষ্টরূপে সংজ্ঞা দেয়নি। এটি এখনও কার্যকর হয় না, যদি না আপনি উত্তরগুলির ওপির মন্তব্যগুলি না পড়ে (জিনিসগুলি যখন নাশপাতি আকারে পরিণত হয় তখন আমি মুছে ফেলা হয়েছিল সেগুলি সহ)।
পেভিয়াম

উত্তর:


43

আমার sed(ম্যাক ওএস এক্স) কাজ করে নি +। আমি *পরিবর্তে চেষ্টা করেছি এবং আমি pমুদ্রণ ম্যাচের জন্য ট্যাগ যুক্ত করেছি :

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

কমপক্ষে একটি সংখ্যার চরিত্রটি মিলে যাওয়ার জন্য +, আমি ব্যবহার করব:

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

আপনাকে ধন্যবাদ, এটি একবারে আমার পরিবর্তে + এর পরিবর্তে * ব্যবহার করার জন্যও কাজ করেছিল।
স্টাফেন

4
... এবং ম্যাচটি মুদ্রণের জন্য "পি" বিকল্পটি, যা সম্পর্কে আমি জানতাম না। আবার ধন্যবাদ.
স্টাফেন

4
আমাকে পালাতে হয়েছিল +এবং তারপরে এটি আমার পক্ষে কাজ করেছিল:sed -n 's/^.*abc\([0-9]\+\)xyz.*$/\1/p'
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছিল।

4
এর কারণ আপনি আধুনিক আর ফর্ম্যাটটি ব্যবহার করছেন না তাই + এটি একটি আদর্শ চরিত্র এবং আপনার এটি {,} বাক্য গঠন সহ প্রকাশ করার কথা। আপনি আধুনিক আর ফর্ম্যাটটি ট্রিগার করতে ব্যবহার-ই সেড বিকল্প যুক্ত করতে পারেন। পুনরায়_ফর্ম্যাট (7) দেখুন, বিশেষত DESCRIPTION বিকাশকারী
অ্যাপ্লিকেশন

35

এটি করার জন্য আপনি সেড ব্যবহার করতে পারেন

 sed -rn 's/.*abc([0-9]+)xyz.*/\1/gp'
  • -n ফলাফল লাইন মুদ্রণ করবেন না
  • -rএটি এটি তৈরি করে যাতে আপনার ক্যাপচার গ্রুপ প্যারেনগুলি পালাতে না পারে ()
  • \1 ক্যাপচার গ্রুপ ম্যাচ
  • /g গ্লোবাল ম্যাচ
  • /p ফলাফল মুদ্রণ

আমি নিজের জন্য একটি সরঞ্জাম লিখেছিলাম যা এটি সহজ করে তোলে

rip 'abc(\d+)xyz' '$1'

4
এটি এখন পর্যন্ত সেরা, এবং সবচেয়ে সুস্পষ্টরূপে উত্তর!
নিক রেইমান

কিছু ব্যাখ্যা সহ, আমাদের সমস্যাটি কী তা বোঝার উপায় এটি আরও ভাল। ধন্যবাদ !
r4phG

17

আমি perlনিজের জন্য এটি সহজ করতে ব্যবহার করি। যেমন

perl -ne 'print $1 if /.*abc([0-9]+)xyz.*/'

এটি পার্ল চালায়, -nঅপশনটি পার্লকে এসটিডিআইএন থেকে একবারে এক লাইনে পড়তে এবং কোডটি কার্যকর করতে নির্দেশ দেয়। -eবিকল্প চালানোর নির্দেশ নির্দিষ্ট করে।

নির্দেশটি পঠিত রেখায় একটি রেজিএক্সপ্যাক চালায় এবং যদি এটি ব্র্যাকের প্রথম সেট ( $1) এর সামগ্রীগুলি মুদ্রণ করে তবে তা মিলে যায় ।

আপনি এটি করতে পারেন শেষ পর্যন্ত একাধিক ফাইলের নামও। যেমন

perl -ne 'print $1 if /.*abc([0-9]+)xyz.*/' example1.txt example2.txt


ধন্যবাদ, তবে আমাদের কাছে পার্লের অ্যাক্সেস নেই, এই কারণেই আমি সেড / অ্যাজক / গাওক সম্পর্কে জিজ্ঞাসা করছিলাম।
স্টাফেন

5

যদি আপনার সংস্করণটিকে grepসমর্থন করে তবে আপনি -oমুদ্রণের বিকল্পটি ব্যবহার করতে পারেন কেবল আপনার regexp সাথে মেলে এমন যেকোনো লাইনের অংশ।

যদি না হয় তবে sedআমি এখানে সেরাটি নিয়ে আসতে পারি:

sed -e '/[0-9]/!d' -e 's/^[^0-9]*//' -e 's/[^0-9]*$//'

... যা কোনও অঙ্ক ছাড়াই মুছে ফেলা / এড়িয়ে চলে এবং বাকী রেখাগুলির জন্য, সমস্ত নেতৃস্থানীয় এবং অনুসরণকারী অ-অঙ্কের অক্ষর সরিয়ে দেয়। (আমি কেবল অনুমান করছি যে আপনার উদ্দেশ্য হ'ল প্রতিটি লাইন থেকে একটি সংখ্যা বের করা)

এর মতো কিছু নিয়ে সমস্যা:

sed -e 's/.*\([0-9]*\).*/&/' 

.... বা

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

... এটি sedকেবল "লোভী" ম্যাচটিকে সমর্থন করে ... তাই প্রথমটি * * বাকী লাইনের সাথে মিলবে। অ-লোভী মিল অর্জন করার জন্য ... বা sedপারেলের সাথে সামঞ্জস্যপূর্ণ বা এর এক্সটেনশনের সাথে অন্যান্য এক্সটেনশনের কোনও সংস্করণ অর্জন করতে আমরা অবহেলিত চরিত্রের ক্লাস ব্যবহার করতে না পারলে আমরা প্যাটার্ন স্পেসের সাথে একটি নির্দিষ্ট প্যাটার্ন ম্যাচটি বের করতে পারি না (একটি লাইন )।


আপনি কেবল আপনার দুটি sedকমান্ড এইভাবে একত্রিত করতে পারেন :sed -n 's/[^0-9]*\([0-9]\+\).*/\1/p'
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া।

এর আগে গ্রেপ-এ বিকল্প সম্পর্কে জানতেন না। জেনে ভালো লাগল. তবে এটি পুরো ম্যাচটি মুদ্রণ করে, "(...)" নয়। সুতরাং আপনি যদি "abc ([[: अंक:]] +) xyz" এর সাথে মিলে থাকেন তবে আপনি "এবিসি" এবং "এক্সওয়াইজ" পাশাপাশি অঙ্কগুলি পাবেন।
স্টাফেন

আমাকে মনে করিয়ে দেওয়ার জন্য ধন্যবাদ grep -o! আমি এটি করার চেষ্টা করছিলাম sedএবং কয়েকটি লাইনে একাধিক মিল খুঁজে পাওয়ার জন্য আমার প্রয়োজনের সাথে লড়াই করেছি। আমার সমাধান stackoverflow.com/a/58308239/117471
ব্রুনো Bronosky

3

আপনি দখল করা গোষ্ঠীটি অ্যাক্সেস করতে এর awkসাথে ব্যবহার করতে পারেন match():

$ awk 'match($0, /abc([0-9]+)xyz/, matches) {print matches[1]}' file
12345

এটি প্যাটার্নটি মেলাতে চেষ্টা করে abc[0-9]+xyz। এটি যদি এটি করে থাকে তবে এটি এর স্লাইসগুলি অ্যারেতে সঞ্চয় করে matches, যার প্রথম আইটেমটি ব্লক [0-9]+। যেহেতু match() সেই স্ট্রিংটি শুরু হয় যেখানে অক্ষরের অবস্থান বা সূচকটি প্রত্যাবর্তন করে (1, এটি স্ট্রিংয়ের শুরুতে শুরু হয়) , এটি printক্রিয়াকে ট্রিগার করে ।


সঙ্গে grepআপনি একটি বর্ণন-পিছনে এবং চেহারা-এগিয়ে ব্যবহার করতে পারেন:

$ grep -oP '(?<=abc)[0-9]+(?=xyz)' file
12345

$ grep -oP 'abc\K[0-9]+(?=xyz)' file
12345

এই চেক প্যাটার্ন [0-9]+যখন এটি মধ্যে ঘটে abcএবং xyzএবং মাত্র ডিজিটের ছাপে।


2

পার্ল হ'ল পরিষ্কার বাক্য গঠন, তবে আপনার যদি পার্ল না থাকে (সর্বদা সেখানে থাকে না, আমি বুঝতে পারি), তবে জেনসব বৈশিষ্ট্যটি ব্যবহার করা গেম এবং একটি রেজেক্সের উপাদানগুলি ব্যবহার করার একমাত্র উপায়।

gawk '/abc[0-9]+xyz/ { print gensub(/.*([0-9]+).*/,"\\1","g"); }' < file

নমুনা ইনপুট ফাইলের আউটপুট হবে

12345

দ্রষ্টব্য: জেনসুব পুরো রেনেক্সকে (// এর মধ্যে) প্রতিস্থাপন করে, সুতরাং প্রতিস্থাপনের সংখ্যার আগে এবং পরে পাঠ্য থেকে মুক্তি পাওয়ার জন্য আপনাকে * * স্থাপন করতে হবে ([0-9] +) এর আগে এবং পরে।


4
একটি চালাক, কার্যক্ষম সমাধান যদি আপনার গাওক ব্যবহার করতে (বা চান) প্রয়োজন হয়। আপনি এটি উল্লেখ করেছেন, তবে স্পষ্টরূপে: নন-জিএনইউ অজকে জেনসব () নেই, এবং তাই এটি সমর্থন করে না।
সিনকোডেনদা

চমৎকার! তবে, match()ধরা পড়া গোষ্ঠীগুলিতে অ্যাক্সেস করার জন্য ব্যবহার করা ভাল । এই জন্য আমার উত্তর দেখুন ।
ফেডরকিই 'এসও ক্ষতিগ্রস্থ হওয়া বন্ধ করুন'

1

আপনি যদি লাইনগুলি নির্বাচন করতে চান তবে যে বিটগুলি চান না তা বের করে দিন:

egrep 'abc[0-9]+xyz' inputFile | sed -e 's/^.*abc//' -e 's/xyz.*$//'

এটি মূলত আপনি যে লাইনের সাথে চান তা নির্বাচন করে egrepএবং তারপরে sedসংখ্যাটির আগে এবং পরে বিটগুলি সরিয়ে ফেলার জন্য ব্যবহার করে।

আপনি এখানে এটি কর্মে দেখতে পারেন:

pax> echo 'a
b
c
abc12345xyz
a
b
c' | egrep 'abc[0-9]+xyz' | sed -e 's/^.*abc//' -e 's/xyz.*$//'
12345
pax> 

আপডেট: স্পষ্টতই যদি আপনি প্রকৃত পরিস্থিতি আরও জটিল হন তবে আমার কাছে আরইএস সংশোধন করা দরকার। উদাহরণস্বরূপ যদি আপনার শুরুতে এবং শেষে শূন্য বা আরও বেশি অ-সংখ্যাগুলির মধ্যে সর্বদা একক সংখ্যা সমাহিত থাকে:

egrep '[^0-9]*[0-9]+[^0-9]*$' inputFile | sed -e 's/^[^0-9]*//' -e 's/[^0-9]*$//'

আকর্ষণীয় ... সুতরাং কোনও জটিল নিয়মিত এক্সপ্রেশন প্রয়োগ করার এবং (...) বিভাগে যা আছে ঠিক ফিরে পাওয়ার কোনও সহজ উপায় নেই? আপনি এখানে প্রথমে গ্রেপ দিয়ে তারপর সেড দিয়ে যা করেছেন তা দেখার সময়, আমাদের আসল পরিস্থিতি "এবিসি" এবং "জাইজ" বাদ দেওয়ার চেয়ে আরও জটিল। নিয়মিত এক্সপ্রেশনটি ব্যবহৃত হয় কারণ আমি যে পাঠ্যটি বের করতে চাইছি তার উভয় পাশে প্রচুর ভিন্ন পাঠ্য উপস্থিত হতে পারে।
স্টাফেন

আমি নিশ্চিত সেখানে আছি হয় একটি ভাল উপায় যদি মাঝামাঝি সত্যিই জটিল। সম্ভবত আপনি যদি আরও কয়েকটি উদাহরণ বা আরও বিশদ বিবরণ সরবরাহ করে থাকেন তবে আমরা আমাদের উত্তর অনুসারে সামঞ্জস্য করতে পারি।
প্যাক্সিডিয়াবলো

0

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

যেহেতু ওপি'র প্রয়োজনটি একটি প্যাটার্ন থেকে একটি গ্রুপ বের করা, তাই ব্যবহারের grep -oজন্য 2 টি পাসের প্রয়োজন হবে। তবে, আমি এখনও এটি কাজটি সর্বাধিক স্বজ্ঞাত উপায় বলে মনে করি।

$ cat > example.txt <<TXT
a
b
c
abc12345xyz
a
abc23451xyz asdf abc34512xyz
c
TXT

$ cat example.txt | grep -oE 'abc([0-9]+)xyz'
abc12345xyz
abc23451xyz
abc34512xyz

$ cat example.txt | grep -oE 'abc([0-9]+)xyz' | grep -oE '[0-9]+'
12345
23451
34512

যেহেতু প্রসেসরের সময়টি মূলত ফ্রি তবে মানুষের পাঠযোগ্যতা অমূল্য, তাই আমি এই প্রশ্নটির উপর ভিত্তি করে আমার কোডটি রিফ্যাক্টর করি, "এখন থেকে এক বছর পর, আমি কী ভাবব যে এটি করে?" প্রকৃতপক্ষে, আমি যে কোডটি প্রকাশ্যে বা আমার দলের সাথে ভাগ করে নিতে চাইছি তার জন্য, আমি man grepদীর্ঘ বিকল্পগুলি কী তা নির্ধারণ করতে এবং সেগুলি বিকল্পের পরিবর্তে খুলব । তাই ভালো:grep --only-matching --extended-regexp


-1

আপনি শেল দিয়ে এটি করতে পারেন

while read -r line
do
    case "$line" in
        *abc*[0-9]*xyz* ) 
            t="${line##abc}"
            echo "num is ${t%%xyz}";;
    esac
done <"file"

-3

অজস্র জন্য। আমি নিম্নলিখিত স্ক্রিপ্ট ব্যবহার করব:

/.*abc([0-9]+)xyz.*/ {
            print $0;
            next;
            }
            {
            /* default, do nothing */
            }

এটি সংখ্যার মান আউটপুট দেয় না ([0-9+]), এটি সম্পূর্ণ লাইনটিকে আউটপুট করে।
লাকাটা

-3
gawk '/.*abc([0-9]+)xyz.*/' file

4
এটি কাজ করে না বলে মনে হচ্ছে। এটি ম্যাচের পরিবর্তে পুরো লাইনটি মুদ্রণ করে।
স্টাফেন

আপনার নমুনা ইনপুট ফাইলে, সেই প্যাটার্নটি সম্পূর্ণ লাইন। ঠিক ??? আপনি যদি জানেন প্যাটার্ন একটি নির্দিষ্ট ক্ষেত্রের মধ্যে হতে যাচ্ছে: $ 1, $ 2 ব্যবহার ইত্যাদি .. যেমন হাবা '$ 1 ~ /.*abc([0-9]+)xyz.*/' ফাইল
ghostdog74
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.