শেল ভেরিয়েবলটিকে একটি / প্যাটার্ন / এজেড হিসাবে পাস করুন


59

আমার শেল ফাংশনগুলির একটিতে নিম্নলিখিতটি থাকা:

function _process () {
  awk -v l="$line" '
  BEGIN {p=0}
  /'"$1"'/ {p=1}
  END{ if(p) print l >> "outfile.txt" }
  '
}

, সুতরাং যখন হিসাবে ডাকা হয় _process $arg, হিসাবে $argপাস করা হয় $1এবং অনুসন্ধান নিদর্শন হিসাবে ব্যবহৃত হয়। এটি এইভাবে কাজ করে, কারণ শেলটি $1অজগর প্যাটার্নের জায়গায় প্রসারিত হয়! এছাড়াও lঘোষিত হওয়ার সাথে সাথে awk প্রোগ্রামের অভ্যন্তরেও ব্যবহার করা যেতে পারে -v l="$line"। সব ঠিক.

পরিবর্তনশীল হিসাবে অনুসন্ধানের জন্য কী একই পদ্ধতিতে প্যাটার্ন দেওয়া সম্ভব?

নিম্নলিখিতগুলি কাজ করবে না,

awk -v l="$line" -v search="$pattern" '
  BEGIN {p=0}
  /search/ {p=1}
  END{ if(p) print l >> "outfile.txt" }
  '

, খালি /search/হিসাবে পরিবর্তনশীল হিসাবে ব্যাখ্যা করবে না , পরিবর্তে আক্ষরিক।

উত্তর:


46

অজকের ~অপারেটরটি ব্যবহার করুন এবং আপনার ডানদিকে আক্ষরিক রেজেক্স সরবরাহ করার দরকার নেই:

function _process () {
    awk -v l="$line" -v pattern="$1" '
        $0 ~ pattern {p=1} 
        END {if(p) print l >> "outfile.txt"}
    '  
}

যদিও এটি আরও কার্যকর হবে (পুরো ফাইলটি পড়তে হবে না)

function _process () {
    grep -q "$1" && echo "$line"
}

প্যাটার্ন উপর নির্ভর করে, চাইতে পারেন grep -Eq "$1"


এটি হ'ল এটি আমার সমাধানের মতো সমাধান করে (1 ম উদাহরণ), কারণ এটি শব্দার্থকে রাখে, যা আমার লক্ষ্য ছিল। ধন্যবাদ।
ব্রাঙ্কুইটো

1
আমি বিগইএন ব্লকটি অপসারণের বিষয়টি লক্ষ্য করিনি: একটি নিরাক্ষরযুক্ত ভেরিয়েবলটিকে একটি সংখ্যার প্রসঙ্গে বা অন্যথায় খালি স্ট্রিং হিসাবে 0 হিসাবে বিবেচনা করা হবে। সুতরাং, একটি নিযুক্ত if (p) ...
স্বাক্ষরযুক্ত

হ্যাঁ আমি লক্ষ্য করেছি, এটি বিগইন ব্লকে প্রতিবার শূন্যে সেট করা দরকার, যেমন এটি স্যুইচ হিসাবে কাজ করে। তবে মজার বিষয় হল আমি এখন স্ক্রিপ্ট ব্যবহার করে চেষ্টা করেছি $0 ~ pattern, এবং এটি কাজ করে না, তবে /'"$1"'/এটি কাজ করে !? : ও
ব্রাঙ্কুইটো

হয়তো এটা পথ সঙ্গে কি কিছু আছে $lineপ্রাপ্ত করা হয়, প্যাটার্ন অনুসন্ধান আউটপুট সম্পন্ন হবে whois $line, $lineএকটি সময় ফাইল থেকে আসছে ব্লক না।
ব্রাঙ্কুইটো

দয়া করে এর বিষয়বস্তুগুলি প্রদর্শন করুন $line- সঠিক ফর্ম্যাটের জন্য আপনার প্রশ্নে এটি করুন।
গ্লেন জ্যাকম্যান

17
awk  -v pattern="$1" '$0 ~ pattern'

এর awkমধ্যে এএনএসআই সি এস্কেপ সিকোয়েন্সগুলি ( \nনতুন লাইনের \fজন্য, ফর্ম ফিডের \\জন্য, ব্যাকস্ল্যাশের জন্য এবং এর মতো) প্রসারিত হওয়ার ক্ষেত্রে একটি সমস্যা রয়েছে $1। সুতরাং এটি $1ব্যাকস্ল্যাশ অক্ষরগুলি থাকে যা নিয়মিত এক্সপ্রেশনগুলিতে (জিএনইউ awk৪.২ বা তারপরের সাথে , যে মানগুলি শুরু হয় @/এবং শেষ /হয় তাও একটি সমস্যা ) থাকে তবে এটি একটি সমস্যা হয়ে দাঁড়ায়। আরেকটি পদ্ধতির যে সমস্যাটি ভোগ করে না তা হ'ল এটি লিখুন:

PATTERN=$1 awk '$0 ~ ENVIRON["PATTERN"]'

এটি কতটা খারাপ হতে চলেছে তা awkবাস্তবায়নের উপর নির্ভর করবে ।

$ nawk -v 'a=\.' 'BEGIN {print a}'
.
$ mawk -v 'a=\.' 'BEGIN {print a}'
\.
$ gawk -v 'a=\.' 'BEGIN {print a}'
gawk: warning: escape sequence `\.' treated as plain `.'
.
$ gawk5.0.1 -v 'a=@/foo/' BEGIN {print a}'
foo

সকল awks বৈধ পালাবার ক্রম যদিও একই কাজ:

$ a='\\-\b' awk 'BEGIN {print ENVIRON["a"]}' | od -tc
0000000   \   \   -   \   b  \n
0000006

( $aযেমনটি পাসের বিষয়বস্তু )

$ awk -v a='\\-\b' 'BEGIN {print a}' | od -tc
0000000   \   -  \b  \n
0000004

( \\পরিবর্তিত \এবং \bএকটি ব্যাকস্পেস অক্ষরে পরিবর্তন করা হয়েছে)।


সুতরাং আপনি বলছেন যে প্যাটার্নটি উদাহরণস্বরূপ যদি \d{3}তিনটি সংখ্যা খুঁজে পাওয়া যায় তবে এটি প্রত্যাশার মতো কাজ করে না, যদি আমি আপনাকে ভালভাবে বুঝতে পারি?
ব্রাঙ্কুইটো

2
জন্য \dযা বৈধ সি পালাবার ক্রম, যে আপনার উপর নির্ভর করে নয় awk(রান বাস্তবায়ন awk -v 'a=\d{3}' 'BEGIN{print a}'চেক করতে)। তবে \` or \ b , yes definitely. (BTW, I don't know of any awk implementations that understands \ d` এর জন্য অঙ্ক হিসাবে অর্থ)।
স্টাফেন চেজেলাস

এটি বলে: অজানা সতর্কতা - এস্কেপ সিকোয়েন্স \d' treated as plain ডি 'ডি {3}, সুতরাং আমার ধারণা এই ক্ষেত্রে আমার কোনও সমস্যা হবে?
ব্রাঙ্কুইটো

1
দুঃখিত, আমার খারাপ, আমার উত্তরে একটি টাইপ ছিল। তারপর এনভায়রনমেন্ট ভেরিয়েবল নাম মেলে হয়েছে ENVIRON["PATTERN"]জন্য PATTERNএনভায়রনমেন্ট ভেরিয়েবল। আপনি যদি শেল ভেরিয়েবল ব্যবহার করতে চান তবে আপনাকে প্রথমে এটি রফতানি করতে হবে ( export variable) অথবা ENV=VALUE awk '...ENVIRON["ENV"]'আমার উত্তর অনুসারে এনভ-ভার পাসিং বাক্য গঠনটি ব্যবহার করতে হবে ।
স্টাফেন চেজেলাস

1
কারণ পরিবেশে এটি একটি কমান্ডের কাছে যাওয়ার জন্য আপনাকে শেল পরিবর্তনশীল রফতানি করতে হবে।
স্টাফেন চেজেলাস

5

এর মতো কিছু চেষ্টা করুন:

awk -v l="$line" -v search="$pattern" 'BEGIN {p=0}; { if ( match( $0, search )) {p=1}}; END{ if(p) print l >> "outfile.txt" }'

এটি যদি /regex/প্যাটার্ন সন্ধানের ক্ষেত্রে একই আচরণ করে তবে এটি একটি দুর্দান্ত সমাধান হতে পারে। আমি চেষ্টা করব.
ব্রাঙ্কুইটো

1
আমি যে দ্রুত পরীক্ষাগুলি চালিয়েছি তা একই কাজ করেছে বলে মনে হয়েছিল, তবে আমি এটির গ্যারান্টি
দেওয়াও

0

না, তবে আপনি কেবলমাত্র প্যাটার্নটি ডাবল-কোটেড স্ট্রিংয়ে ফাঁকে ফাঁকে ফাঁকে যেতে পারেন:

awk -v l="$line" "BEGIN {p=0}; /$pattern/ {p=1}; END{ if(p) print l >> \"outfile.txt\" }"

নোট করুন যে আপনাকে এখন ডাবল-কোট করা অ্যাজক আক্ষরিক হাত থেকে বাঁচতে হবে, তবে এটি এখনও এটি সম্পাদন করার সহজতম উপায়।


$patternশূন্যস্থান থাকলে এই উপায়ে কি নিরাপদ , উপরে থেকে আমার উদাহরণটি কাজ করবে কারণ "$ 1" ডাবল উদ্ধৃতি দিয়ে $ 1 সুরক্ষিত আছে, তবে আপনার ক্ষেত্রে কী ঘটে তা শিউর করবেন না।
ব্রাঙ্কুইটো

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

4
তবে যদি $patternএতে থাকে ^/ {system("rm -rf /")};তবে আপনি বড় সমস্যায় পড়েছেন।
স্টাফেন চেজেলাস

সমস্ত "" আবৃত রেখে, কেবল এই পদ্ধতির ক্ষতিটিই কি?
ব্রাঙ্কুইটো

-3

আপনি eval ফাংশনটি ব্যবহার করতে পারেন যা এই উদাহরণটি সমাধান করে উদাহরণস্বরূপ চালানোর আগে জাল ভেরিয়েবল।

nets="searchtext"
eval "awk '/"${nets}"/'" file.txt
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.