নিয়মিত এক্সপ্রেশন ব্যবহার করে ব্যাশে অনুসন্ধান এবং প্রতিস্থাপন করুন


161

আমি এই উদাহরণটি দেখেছি:

hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//[0-9]/}

যা এই বাক্য গঠনটি অনুসরণ করে: ${variable//pattern/replacement}

দুর্ভাগ্যক্রমে patternক্ষেত্রটি পুরো রেজেক্স সিনট্যাক্সকে সমর্থন করে বলে মনে হচ্ছে না (যদি আমি ব্যবহার করি .বা \sউদাহরণস্বরূপ, এটি আক্ষরিক অক্ষরের সাথে মেলে চেষ্টা করে)।

আমি কীভাবে পুরো রেজেক্স সিনট্যাক্স ব্যবহার করে কোনও স্ট্রিং সন্ধান / প্রতিস্থাপন করতে পারি?


এখানে একটি সংশ্লিষ্ট প্রশ্ন পাওয়া গেছে: stackoverflow.com/questions/5658085/...
jheddings

2
এফওয়াইআই, \sস্ট্যান্ডার্ড পসিক্স-সংজ্ঞায়িত নিয়মিত এক্সপ্রেশন সিনট্যাক্সের অংশ নয় (বিআরই বা ইআরই নয়); এটি একটি পিসিআরই এক্সটেনশান, এবং বেশিরভাগ শেল থেকে পাওয়া যায় না। [[:space:]]আরও সার্বজনীন সমতুল্য।
চার্লস ডাফি

1
\sদ্বারা প্রতিস্থাপিত করা যাবে [[:space:]], উপায় দ্বারা, .দ্বারা ?, এবং বেসলাইন শেল প্যাটার্ন ভাষা থেকে extglob এক্সটেনশন ঐচ্ছিক উপগোষ্ঠী, পুনরাবৃত্তি গোষ্ঠী ভালো জিনিস জন্য ব্যবহার করা যেতে পারে, এবং মত।
চার্লস ডাফি 5:25


আমি এটি সোলারিসে 4.1.11 বাশ সংস্করণে ব্যবহার করি ... প্রতিধ্বনি {{হ্যালো // [0-9] final চূড়ান্ত স্ল্যাশের অভাব লক্ষ্য করুন।
ড্যানিয়েল লিস্টন

উত্তর:


175

সেড ব্যবহার করুন :

MYVAR=ho02123ware38384you443d34o3434ingtod38384day
echo "$MYVAR" | sed -e 's/[a-zA-Z]/X/g' -e 's/[0-9]/N/g'
# prints XXNNNNNXXXXNNNNNXXXNNNXNNXNNNNXXXXXXNNNNNXXX

নোট করুন যে পরবর্তীগুলি -eক্রমে প্রক্রিয়া করা হয়। এছাড়াও, gঅভিব্যক্তির পতাকাটি ইনপুটটির সমস্ত উপস্থিতির সাথে মিলবে।

আপনি এই পদ্ধতিটি ব্যবহার করে নিজের পছন্দসই সরঞ্জামটিও চয়ন করতে পারেন, যেমন পার্ল, অ্যাজক, যেমন:

echo "$MYVAR" | perl -pe 's/[a-zA-Z]/X/g and s/[0-9]/N/g'

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


আমি কেবল বলতে পারি এটি কেবলমাত্র একক প্রতিস্থাপন করে। এটি পোস্ট করার কোডের মতো প্যাটার্নের সমস্ত ঘটনা প্রতিস্থাপন করার কোনও উপায় আছে কি?
লানারু

আমি একাধিক প্রতিস্থাপনের পাশাপাশি বিশ্বব্যাপী প্যাটার্ন মেলানোর জন্য আমার উত্তর আপডেট করেছি। যদি এটি সাহায্য করে তবে আমাকে জানান।
জেহডিংস

অনেক ধন্যবাদ! কৌতূহলের বাইরে আপনি কেন এক লাইনের সংস্করণ থেকে (আপনার মূল উত্তরে) দ্বি-লাইনারে স্যুইচ করলেন?
ল্যানারু

9
ব্যবহার sedবা অন্যান্য বাহ্যিক সরঞ্জাম প্রক্রিয়া আরম্ভের সময় কারণে ব্যয়বহুল। আমি বিশেষত অল-ব্যাশ সমাধানটি অনুসন্ধান করেছি, কারণ আমি sedআমার লুপের প্রতিটি আইটেমের জন্য কল করার চেয়ে ব্যাশ বিকল্পগুলি 3x এর চেয়ে বেশি দ্রুত গতিতে পেয়েছি।
rr-

6
@ সিরোস্যান্টিলি 六四 事件 法轮功 纳米比亚 威 视, মঞ্জুর, এটি সাধারণ জ্ঞান, তবে এটি বুদ্ধিমান হয় না। হ্যাঁ, বাশ যা-ই হোক না কেন ধীরে ধীরে - তবে সাব-শেলগুলি এড়ানো ভাল-লিখিত বাশ হ'ল আক্ষরিক অর্থে বাশের চেয়ে তীব্রতার আদেশ যা প্রতিটি ছোট ছোট কাজের জন্য বাহ্যিক সরঞ্জামকে ডাকে। এছাড়াও, ভালভাবে লিখিত শেল স্ক্রিপ্টগুলি দ্রুত দোভাষী দ্বারা উপকৃত হবে (যেমন ksh93, যা অ্যাডকের সমান পারফরম্যান্স নিয়েছে), যেখানে খারাপভাবে লিখিত রয়েছে সেগুলির জন্য কিছুই করার নেই।
চার্লস ডাফি

133

এটি আসলে খাঁটি বাশে করা যেতে পারে:

hello=ho02123ware38384you443d34o3434ingtod38384day
re='(.*)[0-9]+(.*)'
while [[ $hello =~ $re ]]; do
  hello=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
done
echo "$hello"

...উৎপাদনের...

howareyoudoingtodday

2
কিছু আমাকে বলে এইসব প্রেম হবে: stackoverflow.com/questions/5624969/... =)
nickl-

=~চাবিকাঠি তবে কিছুটা আড়ষ্ট, লুপটিতে পুনরায় নিয়োগ দেওয়া। @ ঝেডিডিংস সলিউশন 2 বছর আগে আরেকটি ভাল বিকল্প - কলিং সেড বা পার্ল)।
ব্রেন্ট ফাউস্ট

3
কল করা sedবা perlবুদ্ধিমান, যদি প্রতিটি অনুরোধকে ইনপুটটির একক লাইন থেকে বেশি প্রক্রিয়া করতে ব্যবহার করা হয়। একটি আউটপুট প্রবাহ প্রক্রিয়া করার জন্য একটি লুপ ব্যবহার করার বিপরীতে লুপের অভ্যন্তরে এ জাতীয় সরঞ্জাম চালু করা বোকামি।
চার্লস ডাফি

2
অবগতির জন্য, zsh, এটা শুধু $matchপরিবর্তে $BASH_REMATCH। (আপনি এটির সাথে setopt bash_rematch
মারিয়ান

এটি অদ্ভুত - যদিও zsh কোনও পসিক্স শেল হওয়ার চেষ্টা করে না, এটি যুক্তিযুক্তভাবে পসিক্স-নির্দিষ্ট (শেল বা সিস্টেম-প্রাসঙ্গিক) উদ্দেশ্যে এবং লোয়ারকেস ভেরিয়েবলগুলির জন্য সংরক্ষিত থাকার জন্য সমস্ত ক্যাপ ভেরিয়েবল সম্পর্কে পসিক্স গাইডেন্সের চিঠি অনুসরণ করে following অ্যাপ্লিকেশন ব্যবহার। তবে zsh হ'ল এমন একটি যা অ্যাপ্লিকেশনগুলি চালিত করে না বরং একটি অ্যাপ্লিকেশন নিজেই প্রয়োগ করে, সিস্টেম নেমস্পেসের পরিবর্তে অ্যাপ্লিকেশন ভেরিয়েবল নেমস্পেস ব্যবহারের এই সিদ্ধান্তটি ভয়াবহভাবে বিভ্রান্ত বলে মনে হয়।
চার্লস ডাফি 21

95

এই উদাহরণগুলি ব্যাডে সেড ব্যবহার করার দরকার নেই:

#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day
MYVAR=${MYVAR//[a-zA-Z]/X} 
echo ${MYVAR//[0-9]/N}

আপনি অক্ষর শ্রেণীর বন্ধনী এক্সপ্রেশনও ব্যবহার করতে পারেন

#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day
MYVAR=${MYVAR//[[:alpha:]]/X} 
echo ${MYVAR//[[:digit:]]/N}

আউটপুট

XXNNNNNXXXXNNNNNXXXNNNXNNXNNNNXXXXXXNNNNNXXX

@ লানারু যা জানতে চেয়েছিল তবে আমি যদি প্রশ্নটি সঠিকভাবে বুঝতে পারি তবেই কেন "পূর্ণ" বা পিসিআরই এক্সটেনশনগুলি \s\S\w\W\d\Dপিএইচপি রুবি পাইথন সমর্থিত হিসাবে কাজ করে না। শেল ভিত্তিক নিয়মিত এক্সপ্রেশনগুলির অন্যান্য ফর্মগুলির সাথে সামঞ্জস্য হতে পারে না।

এগুলি কাজ করে না:

#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//\d/}


#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo $hello | sed 's/\d//g'

সমস্ত আক্ষরিক "d" অক্ষর সমেত আউটপুট

ho02123ware38384you44334o3434ingto38384ay

তবে নিম্নলিখিতটি প্রত্যাশার মতো কাজ করে

#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo $hello | perl -pe 's/\d//g'

আউটপুট

howareyoudoingtodday

আশা করি বিষয়গুলি আরও কিছুটা স্পষ্ট করে দেয় তবে আপনি যদি এখনও বিভ্রান্ত না হন তবে ম্যাক ওএস এক্সে আপনি কেন চেষ্টা করবেন না যাতে REG_ENHANCED পতাকা সক্ষম হয়েছে:

#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day;
echo $MYVAR | grep -o -E '\d'

* নিক্সের বেশিরভাগ স্বাদে আপনি কেবলমাত্র নিম্নলিখিত আউটপুটটি দেখতে পাবেন:

d
d
d

nJoy!


6
ক্ষমা হয়? ${foo//$bar/$baz}হয় না এটা fnmatch () - - শৈলী প্যাটার্ন ম্যাচিং POSIX.2 BRE বা ere সিনট্যাক্স।
চার্লস ডাফি

8
... তাই হয়, যেহেতু ${hello//[[:digit:]]/}কাজ, যদি আমরা ফিল্টার করে বের করে শুধুমাত্র চিঠি পূর্বে ডিজিটের চেয়েছিলেন o, ${hello//o[[:digit:]]*}প্রত্যাশিত (fnmatch ধরনে যেহেতু এক তুলনায় একটি সম্পূর্ণরূপে ভিন্ন আচরণ হবে, *সব অক্ষরের সাথে মেলে, বরং অবিলম্বে পূর্বে আইটেমটি পরিবর্তন হতে চেয়ে 0-অর-বেশি)।
চার্লস ডাফি

1
দেখুন pubs.opengroup.org/onlinepubs/9699919799/utilities/... (এবং সব এটি রেফারেন্স দ্বারা অন্তর্ভুক্ত) fnmatch পূর্ণ বৈশিষ্ট জন্য।
চার্লস ডাফি

1
ম্যান বাশ: == এবং! = এর একই প্রাধান্য সহ একটি অতিরিক্ত বাইনারি অপারেটর, = ~ পাওয়া যায় is এটি ব্যবহার করা হলে, অপারেটরের ডানদিকে স্ট্রিং একটি বর্ধিত নিয়মিত অভিব্যক্তি হিসাবে বিবেচনা করা হয় এবং তদনুসারে মিলিত হয় (রেজেেক্স (3) হিসাবে)।
নিকেল-

1
@ অ্যাডারচক্স আপনি সঠিক, আপনি যে ডিজিটের জন্য ব্যবহার করতে পারেন [0-9]বা[[:digit:]]
নিকল-

13

যদি আপনি বারবার কল করে থাকেন এবং পারফরম্যান্সের সাথে সম্পর্কিত হন, এই পরীক্ষাটি প্রকাশ করে যে বেসড পদ্ধতিটি সিডে ফোরিং এবং সম্ভবত অন্য কোনও বাহ্যিক প্রক্রিয়ার চেয়ে 15x ডলার দ্রুত।

hello=123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X

P1=$(date +%s)

for i in {1..10000}
do
   echo $hello | sed s/X//g > /dev/null
done

P2=$(date +%s)
echo $[$P2-$P1]

for i in {1..10000}
do
   echo ${hello//X/} > /dev/null
done

P3=$(date +%s)
echo $[$P3-$P2]

1
আপনি কাটাচামচ হ্রাস করার জন্য উপায় করতে আগ্রহী হন তবে, শব্দ অনুসন্ধান newConnector মধ্যে এই উত্তর কিভাবে ব্যাশ একটি কমান্ডের আউটপুট একটি পরিবর্তনশীল সেট করতে?
এফ হাউরি

8

[[:digit:]]প্যাটার্ন হিসাবে (ডাবল বন্ধনী নোট করুন) ব্যবহার করুন :

$ hello=ho02123ware38384you443d34o3434ingtod38384day
$ echo ${hello//[[:digit:]]/}
howareyoudoingtodday

কেবল উত্তরগুলি সংক্ষিপ্ত করতে চেয়েছিলেন (বিশেষত @ নিকেল-'s এর https://stackoverflow.com/a/22261334/2916086 )।

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