কীভাবে কেবল সেড দিয়ে বন্দী গোষ্ঠীগুলিকে আউটপুট দেওয়া যায়?


277

sedকেবল আটককৃত গ্রুপগুলিকে আউটপুট বলার কি কোনও উপায় আছে ? উদাহরণস্বরূপ ইনপুট দেওয়া:

This is a sample 123 text and some 987 numbers

এবং প্যাটার্ন:

/([\d]+)/

ব্যাক রেফারেন্স দ্বারা ফর্ম্যাট করা পথে আমি কি কেবল 123 এবং 987 আউটপুট পেতে পারি?


দ্রষ্টব্য, গ্রুপ ক্যাপচারের জন্য পতাকা sedসহ বর্ধিত নিয়মিত অভিব্যক্তি চালু করা দরকার -E
পিটারহ - মনিকা পুনরায় ইনস্টল করুন

উত্তর:


333

এটির কাজ করার মূল চাবিকাঠিটি হ'ল আপনি sedকী আউটপুট হতে চান না তা বাদ দেওয়ার পাশাপাশি আপনি কী চান তা উল্লেখ করতে হবে।

string='This is a sample 123 text and some 987 numbers'
echo "$string" | sed -rn 's/[^[:digit:]]*([[:digit:]]+)[^[:digit:]]+([[:digit:]]+)[^[:digit:]]*/\1 \2/p'

এটি বলে:

  • প্রতিটি লাইন মুদ্রণ ডিফল্ট না ( -n)
  • শূন্য বা আরও অ-সংখ্যা বাদ দিন
  • এক বা একাধিক সংখ্যা অন্তর্ভুক্ত করুন
  • এক বা একাধিক অ-অঙ্ক বাদ দিন
  • এক বা একাধিক সংখ্যা অন্তর্ভুক্ত করুন
  • শূন্য বা আরও অ-সংখ্যা বাদ দিন
  • প্রতিস্থাপন মুদ্রণ ( p)

সাধারণভাবে, আপনি sedপিছনে রেফারেন্স ব্যবহার করে যা ক্যাপচার করেন তা বন্ধনী এবং আউটপুট ব্যবহার করে দলগুলি ক্যাপচার করে:

echo "foobarbaz" | sed 's/^foo\(.*\)baz$/\1/'

"বার" আউটপুট হবে। আপনি যদি এক্সটেন্ডেড রেজেক্সের জন্য -r( -Eওএস এক্সের জন্য) ব্যবহার করেন তবে আপনার প্রথম বন্ধনী থেকে বাঁচার দরকার নেই:

echo "foobarbaz" | sed -r 's/^foo(.*)baz$/\1/'

9 টি পর্যন্ত ক্যাপচার গ্রুপ এবং তাদের পিছনে উল্লেখ থাকতে পারে। গ্রুপগুলি উপস্থিত হওয়ার সাথে সাথে পিছনের রেফারেন্সগুলি গণনা করা হয়েছে তবে সেগুলি কোনও ক্রমে ব্যবহার করা যেতে পারে এবং পুনরাবৃত্তি করা যেতে পারে:

echo "foobarbaz" | sed -r 's/^foo(.*)b(.)z$/\2 \1 \2/'

আউটপুটস "এ বার এ"।

আপনার যদি জিএনইউ থাকে grep(এটি ওএস এক্স সহ বিএসডি-তেও কাজ করতে পারে):

echo "$string" | grep -Po '\d+'

বা বৈচিত্রগুলি যেমন:

echo "$string" | grep -Po '(?<=\D )(\d+)'

-Pবিকল্প পার্ল সামঞ্জস্যপূর্ণ রেগুলার এক্সপ্রেশন দেয়। দেখুন man 3 pcrepatternবা man 3 pcresyntax


24
একটি নোট হিসাবে, ওএসএক্স মাউন্টেন লায়ন আর গ্রেপ-তে পিসিআরই সমর্থন করে না।
yincrash

1
পার্শ্ব-নোট হিসাবে, গ্রেপ -o বিকল্পটি সোলারিস 9-তে সমর্থিত নয়, এছাড়াও সোলারিস 9 সেড-আরআর বিকল্পটি সমর্থন করে না। :(
ড্যানিয়েল কেটস

7
আপনার সিসাদমিনকে জিএসড ইনস্টল করতে বলুন। কয়েকটা ডোনাট কী পাবেন তা দেখে আপনি অবাক হয়ে যাবেন ...
avgvstvs

3
নোট করুন যে আপনার '(' এবং ')' এর সাথে '\' উপসর্গের দরকার হতে পারে, কেন তা আমি জানি না।
লম্ব্রিক

7
@ লুম্ব্রিক: আপনি যদি sedউদাহরণটির উল্লেখ করছেন , আপনি যদি -rবিকল্পটি (বা -Eওএস এক্স, আইআইআরসি) ব্যবহার করেন তবে আপনাকে প্রথম বন্ধনী থেকে বাঁচতে হবে না। পার্থক্যটি হল বেসিক নিয়মিত এক্সপ্রেশন এবং বর্ধিত নিয়মিত এক্সপ্রেশন ( -r) এর মধ্যে।
পরবর্তী বিজ্ঞপ্তি না হওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

55

শেডের নয়টি পর্যন্ত স্মরণযোগ্য নিদর্শন রয়েছে তবে আপনাকে নিয়মিত অভিব্যক্তির অংশগুলি মনে রাখতে পালানো বন্ধনী ব্যবহার করা দরকার।

উদাহরণ এবং আরও বিশদ জন্য এখানে দেখুন


58
sed -e 's/version=\(.+\)/\1/' input.txtএটি এখনও পুরো ইনপুটটি আউটপুট দেবে t টেক্সট
পাবলো

@ পাবলো, আপনার প্যাটার্নে আপনাকে \+পরিবর্তে লিখতে হবে +। এবং আমি বুঝতে পারি না কেন লোকেরা -eকেবল একটি সেড কমান্ডের জন্য ব্যবহার করে ।
ফ্রেড্রিক গাউস

1
ব্যবহার sed -e -n 's/version=\(.+\)/\1/p' input.txtদেখুন: mikeplate.com/2012/05/09/…
অগ্নি

1
আমি sed -Eতথাকথিত "আধুনিক" বা "বর্ধিত" নিয়মিত এক্সপ্রেশনগুলি ব্যবহার করার পরামর্শ দিচ্ছি যা পার্ল / জাভা / জাভাস্ক্রিপ্ট / গো / যাই হোক না কেন স্বাদ থেকে অনেক বেশি কাছাকাছি দেখায়। (এর সাথে তুলনা grep -Eবা egrep।) ডিফল্ট সিনট্যাক্স ঐ অদ্ভুত পলায়নের নিয়ম আছে এবং "অপ্রচলিত" বলা হয়। দুজনের মধ্যে পার্থক্য সম্পর্কে আরও তথ্যের জন্য, চালান man 7 re_format
অ্যান্ড্রুএফ

31

আপনি গ্রেপ ব্যবহার করতে পারেন

grep -Eow "[0-9]+" file

4
@ ঘোস্টডোগ 74৪: আপনার সাথে একমত হবেন। আমি কীভাবে কেবল বন্দী গোষ্ঠীর আউটপুট এ গ্রো পেতে পারি?
পাবলো

1
@Michael - যে কেন oবিকল্প নেই - unixhelp.ed.ac.uk/CGI/man-cgi?grep : -o, --only-ম্যাচিং দেখান শুধুমাত্র একটি মানানসই লাইনের অংশ ম্যাচ দৃষ্টান্ত
বার্ট এফ

14
@ বার্ট এফ: আমি মিলে যাওয়া অংশটি বুঝতে পেরেছি, তবে এটি গ্রুপটি ক্যাপচার করছে না। আমি যা চাই তা হ'ল এটির মতো ([0-9] +) + আমি কেবলমাত্র ব্যাকরেফারেন্স বা অন্য কোনওভাবে গ্রুপগুলি ক্যাপচার করতে চাই output
পাবলো 12

হ্যালো মাইকেল আপনি কি গ্রেপ্তার দ্বারা n তম ক্যাপচারিত গোষ্ঠীটি বের করতে পেরেছেন?
doc_id

1
@ পাবলো: গ্রেপের কেবলমাত্র মিলে যায় আউটপুটিং। এটিকে একাধিক গোষ্ঠী দেওয়ার জন্য, একাধিক এক্সপ্রেশন ব্যবহার করুন: grep -Eow -e "[0-9]+" -e "[abc]{2,3}"আমি জানি না আপনি কীভাবে এই দুটি এক্সপ্রেশনটি আগের গ্রীপ থেকে পাইপিংয়ের পাশে এক লাইনে থাকতে পারেন (যা এখনও কোনও কাজ করতে পারে না যদি কোনও প্যাটার্ন এক লাইনের সাথে একাধিকবার মেলে তবে )।
idbrii

13

অঙ্কের রান (গুলি)

এই উত্তরটি কোনও সংখ্যা গোষ্ঠীর সাথে কাজ করে। উদাহরণ:

$ echo 'Num123that456are7899900contained0018166intext' |
> sed -En 's/[^0-9]*([0-9]{1,})[^0-9]*/\1 /gp'
123 456 7899900 0018166

প্রসারিত উত্তর।

কেবল আটককৃত গ্রুপগুলিকে আউটপুট দেওয়ার জন্য কি কোনও উপায় আছে?

হ্যাঁ. ক্যাপচার গ্রুপ দ্বারা সমস্ত পাঠ্য প্রতিস্থাপন:

$ echo 'Number 123 inside text' | sed 's/[^0-9]*\([0-9]\{1,\}\)[^0-9]*/\1/'
123

s/[^0-9]*                           # several non-digits
         \([0-9]\{1,\}\)            # followed by one or more digits
                        [^0-9]*     # and followed by more non-digits.
                               /\1/ # gets replaced only by the digits.

বা বর্ধিত বাক্য গঠন (কম ব্যাককোটিস এবং + এর ব্যবহারের অনুমতি দিন) সহ:

$ echo 'Number 123 in text' | sed -E 's/[^0-9]*([0-9]+)[^0-9]*/\1/'
123

সংখ্যা নেই যখন মূল পাঠ্য মুদ্রণ এড়াতে, ব্যবহার করুন:

$ echo 'Number xxx in text' | sed -En 's/[^0-9]*([0-9]+)[^0-9]*/\1/p'
  • (-n) ডিফল্ট হিসাবে ইনপুট মুদ্রণ করবেন না।
  • (/ পি) মুদ্রণ কেবলমাত্র যদি প্রতিস্থাপন করা হয়।

এবং কয়েকটি সংখ্যার সাথে মেলে (এবং সেগুলি মুদ্রণও করতে):

$ echo 'N 123 in 456 text' | sed -En 's/[^0-9]*([0-9]+)[^0-9]*/\1 /gp'
123 456

এটি কোনও সংখ্যা রানের গণনার জন্য কাজ করে:

$ str='Test Num(s) 123 456 7899900 contained as0018166df in text'
$ echo "$str" | sed -En 's/[^0-9]*([0-9]{1,})[^0-9]*/\1 /gp'
123 456 7899900 0018166

যা গ্রেপ কমান্ডের সাথে খুব মিল:

$ str='Test Num(s) 123 456 7899900 contained as0018166df in text'
$ echo "$str" | grep -Po '\d+'
123
456
7899900
0018166

প্রায় \ d

এবং প্যাটার্ন: /([\d]+)/

শেড '\ d' (শর্টকাট) সিনট্যাক্সটি সনাক্ত করে না। উপরে ব্যবহৃত আসকি সমতুল্য [0-9]হুবহু সমতুল্য নয়। একটি বিকল্প বিকল্প হ'ল একটি অক্ষর শ্রেণি ব্যবহার করা: '[[: ডিজিট:]] ``

নির্বাচিত উত্তর সমাধান তৈরি করতে যেমন "চরিত্রের ক্লাসগুলি" ব্যবহার করে:

$ str='This is a sample 123 text and some 987 numbers'
$ echo "$str" | sed -rn 's/[^[:digit:]]*([[:digit:]]+)[^[:digit:]]+([[:digit:]]+)[^[:digit:]]*/\1 \2/p'

এই সমাধানটি কেবলমাত্র (দুই) অঙ্কের অঙ্কের জন্য কাজ করে।

অবশ্যই, শেলের ভিতরে উত্তরটি কার্যকর করা হচ্ছে, আমরা এই জাতীয় উত্তরকে আরও সংক্ষিপ্ত করতে কয়েকটি পরিবর্তনশীল সংজ্ঞায়িত করতে পারি:

$ str='This is a sample 123 text and some 987 numbers'
$ d=[[:digit:]]     D=[^[:digit:]]
$ echo "$str" | sed -rn "s/$D*($d+)$D+($d+)$D*/\1 \2/p"

তবে, যেমন ইতিমধ্যে ব্যাখ্যা করা হয়েছে, একটি s/…/…/gpকমান্ড ব্যবহার করা ভাল:

$ str='This is 75577 a sam33ple 123 text and some 987 numbers'
$ d=[[:digit:]]     D=[^[:digit:]]
$ echo "$str" | sed -rn "s/$D*($d+)$D*/\1 /gp"
75577 33 123 987

এটি সংখ্যার পুনরাবৃত্তি রান এবং একটি সংক্ষিপ্ত (er) কমান্ড উভয়ই কভার করবে।


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

9

আমি বিশ্বাস করি যে প্রশ্নে দেওয়া প্যাটার্নটি কেবল উদাহরণের মাধ্যমে ছিল, এবং লক্ষ্য ছিল কোনও প্যাটার্নের সাথে মেলে ।

আপনি যদি একটি থাকে তাহলে sed প্যাটার্ন মহাকাশে একটি newline এর গনুহ এক্সটেনশন সন্নিবেশ যার ফলে সঙ্গে, এক পরামর্শ হল:

> set string = "This is a sample 123 text and some 987 numbers"
>
> set pattern = "[0-9][0-9]*"
> echo $string | sed "s/$pattern/\n&\n/g" | sed -n "/$pattern/p"
123
987
> set pattern = "[a-z][a-z]*"
> echo $string | sed "s/$pattern/\n&\n/g" | sed -n "/$pattern/p"
his
is
a
sample
text
and
some
numbers

এই উদাহরণগুলি CYGWIN এর সাথে tcsh (হ্যাঁ, আমি এটির ভুল শেলটি জানি ) with (সম্পাদনা করুন: ব্যাশের জন্য, সেটটি এবং আশেপাশের স্থানগুলি সরিয়ে ফেলুন =।)


@ জোসেফ: ধন্যবাদ, তবে আমার কাজের উপর ভিত্তি করে আমি মনে করি যে গ্রেপ আরও প্রাকৃতিক, যেমন ঘোস্টডগ suggested৪ প্রস্তাবিত। শুধুমাত্র পুরো ম্যাচটি নয়, কেবল গ্র্যাপ আউটপুট ক্যাপচার গ্রুপগুলি কীভাবে তৈরি করা যায় তা নির্ধারণ করা দরকার।
পাবলো

2
কেবল একটি নোট, তবে প্লাস চিহ্ন '+' এর অর্থ 'এক বা একাধিক' যা নিদর্শনগুলিতে নিজেকে পুনরাবৃত্তি করার প্রয়োজনীয়তা সরিয়ে ফেলবে। সুতরাং, "[0-9] [0-9] *" হয়ে উঠবে "[0-9] +"
র্যান্ডমইনসানো

4
@ র্যান্ডমআইনসানো: এটি ব্যবহার করার জন্য +আপনাকে এড়াতে বা -rবিকল্পটি ( -Eওএস এক্সের জন্য) ব্যবহার করতে হবে । এছাড়াও আপনি ব্যবহার করতে পারেন \{1,\}(অথবা -rবা -Eপলায়নের ছাড়াই)।
পরবর্তী বিজ্ঞপ্তি না হওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

9

ছেড়ে দিন এবং পার্ল ব্যবহার করুন

যেহেতু sedএটিকে কেটে নয়, এর ঠিক গামছা নিক্ষেপ এবং ব্যবহার পার্ল, অন্তত এটা দিন lsb যখন grepগনুহ এক্সটেনশন নয় :-)

  • পুরো ম্যাচিং অংশটি মুদ্রণ করুন, কোনও মেলানো গোষ্ঠী বা লুকের পিছনে প্রয়োজন নেই:

    cat <<EOS | perl -lane 'print m/\d+/g'
    a1 b2
    a34 b56
    EOS

    আউটপুট:

    12
    3456
  • প্রতি লাইনে একক মিল, প্রায়শই কাঠামোগত ডেটা ক্ষেত্র:

    cat <<EOS | perl -lape 's/.*?a(\d+).*/$1/g'
    a1 b2
    a34 b56
    EOS

    আউটপুট:

    1
    34

    নজরদারি সহ:

    cat <<EOS | perl -lane 'print m/(?<=a)(\d+)/'
    a1 b2
    a34 b56
    EOS
  • একাধিক ক্ষেত্র:

    cat <<EOS | perl -lape 's/.*?a(\d+).*?b(\d+).*/$1 $2/g'
    a1 c0 b2 c0
    a34 c0 b56 c0
    EOS

    আউটপুট:

    1 2
    34 56
  • প্রতি লাইনে একাধিক মিল, প্রায়শই কাঠামোগত ডেটা:

    cat <<EOS | perl -lape 's/.*?a(\d+)|.*/$1 /g'
    a1 b2
    a34 b56 a78 b90
    EOS

    আউটপুট:

    1 
    34 78

    নজরদারি সহ:

    cat EOS<< | perl -lane 'print m/(?<=a)(\d+)/g'
    a1 b2
    a34 b56 a78 b90
    EOS

    আউটপুট:

    1
    3478

1
প্রশ্নের শেষে আপনি কী পেলেন না: "সেড সহ"?
মুনচাইল্ড

@ মুনচাইল্ড গুগলাররা এর কোন চিন্তা করে না।
সিরো সান্তিলি 郝海东 冠状 病 六四 事件

1
আমি এটি দরকারী খুঁজে পেয়েছি। সমস্ত কমান্ড লাইন রেজেক্স সমস্যাগুলি সেড দিয়ে সমাধান করার দরকার নেই।
পিপিপিউল

5

চেষ্টা

sed -n -e "/[0-9]/s/^[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*$/\1 \2 \3 \4 \5 \6 \7 \8 \9/p"

আমি এটি সাইগউইনের অধীনে পেয়েছি:

$ (echo "asdf"; \
   echo "1234"; \
   echo "asdf1234adsf1234asdf"; \
   echo "1m2m3m4m5m6m7m8m9m0m1m2m3m4m5m6m7m8m9") | \
  sed -n -e "/[0-9]/s/^[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*$/\1 \2 \3 \4 \5 \6 \7 \8 \9/p"

1234
1234 1234
1 2 3 4 5 6 7 8 9
$

2

ওপি (গ্রুপগুলি ক্যাপচার) এর জন্য যা চেয়েছিল তা নয় তবে আপনি এটি ব্যবহার করে নম্বরগুলি বের করতে পারেন:

S='This is a sample 123 text and some 987 numbers'
echo "$S" | sed 's/ /\n/g' | sed -r '/([0-9]+)/ !d'

নিম্নলিখিত দেয়:

123
987
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.