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


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.