আমি কীভাবে একটি উপকারের এলএইচএস এবং আরএইচএসে ভেরিয়েবলগুলি ব্যবহার করতে পারি?


60

আমি করতে চাই:

cat update_via_sed.sh | sed 's/old_name/new_name/' > new_update_via_sed.sh

আমার প্রোগ্রামে

তবে আমি যেমন ভেরিয়েবল ব্যবহার করতে চাই eg

old_run='old_name_952'
new_run='old_name_953'

আমি সেগুলি ব্যবহারের চেষ্টা করেছি কিন্তু প্রতিস্থাপনটি ঘটে না (কোনও ত্রুটি নেই)। আমি চেষ্টা করেছি:

cat update_via_sed.sh | sed 's/old_run/new_run/'
cat update_via_sed.sh | sed 's/$old_run/$new_run/'
cat update_via_sed.sh | sed 's/${old_run}/${new_run}/'

উত্তর:


44

আপনি করতে পারেন:

sed "s/$old_run/$new_run/" < infile > outfile

কিন্তু হুঁশিয়ার করে $old_runএকটি রেগুলার এক্সপ্রেশন হিসাবে গ্রহণ করা হবে এবং তাই কোনো বিশেষ অক্ষর আছে যা পরিবর্তনশীল রয়েছে, যেমন /বা .করতে হবে পলান করা । একইভাবে, মধ্যে $new_run, &এবং \অক্ষর বিশেষভাবে চিকিত্সা করা প্রয়োজন হবে এবং আপনি অব্যাহতি হবে /এটা এবং সম্পর্কে newline অক্ষর।

যদি বিষয়বস্তু $old_runবা $new_runনিয়ন্ত্রণ আপনার নিয়ন্ত্রণে না থাকে, তবে সেই পলায়নের কাজটি করা সমালোচনা করা হয়, বা অন্যথায় এই কোডটি কোনও কোড ইনজেকশন দুর্বলতার সমান


3
আমি সেড প্যারামগুলিতে একক উদ্ধৃতি ব্যবহার করছিলাম, ডাবল উদ্ধৃতিতে স্যুইচ করেছি এবং এটি ফাইলের কাজ করেছে। অসাধারণ.
আকাশ

এটা কি sedএকা রেজেেক্স ব্যবহার করবে না তবে sed -E?
কিউই

@ কিউই, না -eএকটি sed এক্সপ্রেশন নির্দিষ্ট করতে হয়, যাতে আপনি একের বেশি ( sed -e exp1 -e exp2ফাইল হিসাবে এবং এক্সপ্রেশন sed -f file -e exp) সংমিশ্রণ করতে পারেন । আপনি -Eকিছু বিভ্রান্তির সাথে বিভ্রান্ত হতে পারেন, সেটিকে BRE এর পরিবর্তে ERE ব্যবহার করতে বলে sed
স্টাফেন চেজেলাস

আমি ভুল টাইপ করেছি, তবে ঠিক আছে, এটি ব্যাখ্যা করে যে কেন আমি -Eকেবলমাত্র বর্ধিত রেইগেক্সকে নিয়মিত না করে ছাড়াই সেড ব্যবহার করে এতগুলি সমস্যা পেয়েছি। ব্যাখ্যার জন্য ধন্যবাদ।
কিউই

@ কিউই, আরও নিয়মিত অভিব্যক্তি সিনট্যাক্সের জন্য কিছু বাস্তবায়ন দ্বারা সমর্থিত আরও বিকল্পগুলির জন্য সংযুক্ত প্রশ্নোত্তরটিওsed দেখুন।
স্টাফেন চেজেলাস

31

এটি কাজ করেছে:

cat update_via_sed.sh | sed 's/'"$old_run"'/'"$new_run"'/'

যেহেতু আমি একই ফাইলটি 'পুনঃব্যবহার' করতে চাইছি বাস্তবে অনুরূপ পদ্ধতির ইচ্ছুক কারও জন্য আমি এটি ব্যবহার করি:

cat update_via_sed.sh | sed 's/'"$old_run"'/'"$new_run"'/' > new_update; mv -f new_update update_via_sed.sh

উপরোক্ত একটি নতুন ফাইল তৈরি করে তারপরে বর্তমান ফাইলটিকে নতুন ফাইলটির নামকরণের চেয়ে বর্তমান ফাইলটি মুছে দেয়।


4
আপনার বিড়াল, এমভি বা অতিরিক্ত '' লাগবে না যতক্ষণ না আপনি সেগুলিতে বিশেষ অক্ষর না রেখে থাকেন। সুতরাং এটি sed -i s/"$old"/"$new"/ update_via_sed.sh। তবে সচেতন থাকুন যে এটি পুরানো এবং নতুন কোনও মানের জন্য কাজ করে না। উদাহরণস্বরূপ এটিতে / ইত্যাদি থাকা উচিত নয়, কারণ পুরানো এখনও অনুসন্ধান এবং $ নতুন প্রতিস্থাপনের ধরণ যেখানে কয়েকটি অক্ষরের বিশেষ অর্থ রয়েছে।
frostschutz

1
sed -i "s/$old/$new/"ঠিক আছে (উপরের সাবধানতা সহ)। কমান্ডের sedপরে সাধারণত বিভাজকটিকে প্রথম চরিত্র হিসাবে বিবেচনা করে s- যেমন আপনার ভেরিয়েবলগুলি স্ল্যাশ ধারণ করে /তবে ( @) তে বলতে না দেয় , আপনি "s @ $ পুরাতন @ $ নতুন @" ব্যবহার করতে পারেন।
পিটার্ফ

22

আপনি সেডে ভেরিয়েবলগুলি যতক্ষণ না এটি ডাবল উদ্ধৃতিতে (একক উদ্ধৃতি নয়) ব্যবহার করতে পারেন:

sed "s/$var/r_str/g" file_name >new_file

আপনার যদি /ভেরিয়েবলে ফরোয়ার্ড স্ল্যাশ ( ) থাকে তবে নীচের মতো আলাদা বিভাজক ব্যবহার করুন

sed "s|$var|r_str|g" file_name >new_file

1
ডাবল উদ্ধৃতি ব্যবহার করা প্রয়োজন উল্লেখ করার জন্য +1। আমার সমস্যা ছিল।
স্পেকলেডকার্প

1
ঠিক কি আমি খুঁজছেন ছিল ব্যবহার সমেত |আমার ক্ষেত্রে হিসাবে, ভেরিয়েবল, যাতে এটা আছে একটি পাথ ধারণ করে /তাতে
yorch

কিছু কারণে পাইপটি |ম্যাকওএস 10.14 এ আমার জন্য কাজ করেছিল, তবে অন্যান্য পৃথককারীরা পছন্দ করেন @বা #না করেন। আমার এনভিও ভারতেও ফরোয়ার্ড স্ল্যাশ ছিল।
ডেভিডকে

21

'ইন-প্লেস' সেড (us-the -i পতাকা) এর উত্তর ছিল। পিটারফকে ধন্যবাদ

sed -i "s@$old@$new@" file

2
আপনার কাছে ভুল জায়গায় উদ্ধৃতি রয়েছে। উদ্ধৃতি অবশ্যই ভেরিয়েবলের কাছাকাছি থাকতে হবে না s@(যা কোনওভাবেই শেলের সাথে বিশেষ নয়)। ভালো লাগার মধ্যে প্রতিটি জিনিস রাখা ভাল sed -i "s@$old@$new@" file। নোট করুন যে -iএকটি আদর্শ sedবিকল্প নয়।
স্টাফেন চেজেলাস

আমি কীভাবে $এই আদেশে পালাতে পারি ? মত, আমি $xxxসামগ্রিকভাবে একটি ভেরিয়েবলের মানতে পরিবর্তন করতে চলেছি $JAVA_HOME। আমি চেষ্টা করেছি sed -i "s@\$xxx@$JAVA_HOME@" file, তবে ত্রুটিটি বলেছেno previous regular expression
হাকুনামী

3

man bash একক উদ্ধৃতি সম্পর্কে এটি দেয়

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

আপনি কমান্ড লাইনে যাই টাইপ করুন না কেন ব্যাশ এটি ব্যাখ্যা করে এবং তারপরে ফলাফলটি প্রোগ্রামে প্রেরণ করে যা এটি প্রেরণ করা হয়েছিল বলে মনে করা হয় this এই ক্ষেত্রে, আপনি যদি sed 's/$old_run/$new_run/'ব্যাশ ব্যবহার করেন , তবে প্রথমে ব্যাশটি দেখতে পাবে sed, এটি এটিকে $PATHভেরিয়েবলের মধ্যে একটি এক্সিকিউটেবল উপস্থিত হিসাবে স্বীকৃতি দেয় । sedএক্সিকিউটেবল একটি ইনপুট প্রয়োজন। বাশ ইনপুটটি সন্ধান করে এবং আবিষ্কার করে 's/$old_run/$new_run/'। একক উদ্ধৃতিগুলি বাশকে তাদের লিখিত সামগ্রীর ব্যাখ্যা না করার জন্য এবং তাদের যেমন আছে তেমন পাস করার জন্য বলেছে। সুতরাং, বাশ তারপরে সেডগুলিতে চলে যায়। শেড একটি ত্রুটি দেয় কারণ $কেবল লাইনের শেষে ঘটতে পারে।

পরিবর্তে যদি আমরা ডাবল উদ্ধৃতি ব্যবহার করি, অর্থাত্, "s/$old_run/$new_run/"তবে বাশ এটিকে দেখায় এবং $old_runএকটি পরিবর্তনশীল নাম হিসাবে ব্যাখ্যা করে এবং একটি বিকল্প তৈরি করে (এই ধাপটি পরিবর্তনশীল সম্প্রসারণ বলা হয়)। এটি প্রকৃতপক্ষে আমাদের যা প্রয়োজন।

তবে, আপনাকে দ্বিগুণ উদ্ধৃতি ব্যবহার করে যত্নবান হতে হবে কারণ, এগুলি প্রথমে ব্যাশ দ্বারা ব্যাখ্যা করা হয় এবং তারপরে সেডকে দেওয়া হয়। সুতরাং, `জাতীয় কিছু চিহ্ন ব্যবহার করার আগে তাদের অবশ্যই পালাতে হবে।


1

উল্লিখিত হওয়ার ঝুঁকিতে - আপনি বিবেচনা করেছেন perl?

যা - অন্যান্য বিষয়গুলির মধ্যে - 'সেড স্টাইল' অপারেশন করা বেশ ভাল, তবে আরও সম্পূর্ণ বৈশিষ্ট্যযুক্ত প্রোগ্রামিং জিনিসযুক্ত um

এটা তোলে দেখায় আপনার উদাহরণ মতো, আপনি করছেন কি আসলে করার চেষ্টা একটি সংখ্যা বাড়ায় করা হয়।

সুতরাং কিভাবে সম্পর্কে:

#!/usr/bin/env perl
use strict;
use warnings 'all'; 

while ( <DATA> ) {
    s/old_name_(\d+)/"old_name_".($1+1)/e;
    print;
}

__DATA__
old_name_932

বা একটি একলাইনার হিসাবে - সেড স্টাইল:

perl -pe 's/old_name_(\d+)/"old_name_".($1+1)/e'

1
$ echo $d1 | sed -i 's/zkserver1/'${d1}'/g' deva_file
sed: -e expression #1, char 26: unterminated `s' command 

ইন $d1আমি সংরক্ষণকারী মান করছি

আমি ভেরিয়েবল থেকে মানটি প্রতিস্থাপন করতে পারি না, তাই এটি নিম্নলিখিত কমান্ডটি ব্যবহার করে কাজ করে যাচ্ছি

echo $d1 | sed -i 's/zkserver1/'"${d1}"'/g' deva_file

ডাবল উদ্ধৃতি চিহ্ন অনুপস্থিত "${d1}", এটি ছিল ত্রুটি


-2

ধরে নেওয়া $old_runএবং $new_runইতিমধ্যে সেট করা হয়েছে:

cat update_via_sed.sh | eval $(print "sed 's/$old_run/$new_run/g'")

এটি পর্দার পরিবর্তন দেখায়। প্রয়োজনে আপনি আউটপুট ফাইলে পুনর্নির্দেশ করতে পারেন।


-2

সেডে ভেরিয়েবল ব্যবহারের জন্য, "" আপনি যে প্যাটার্নটি ব্যবহার করছেন সেটি ভেরিয়েবলটি আবদ্ধ করতে "" ডাবল কোটস ব্যবহার করুন। উদাহরণস্বরূপ: a = "হাই" যদি আপনি কোনও প্যাটার্নে ভেরিয়েবল 'ক' যুক্ত করতে চান তবে আপনি নীচেরটি ব্যবহার করতে পারেন: সেড -n "1, / প্যাটার্ন" $ {a pattern "প্যাটার্ন / পি" ফাইলের নাম


2
এখানে সম্প্রসারিত $aঅনুপ্রেরণা, যার অর্থ এর মানের কোনও ফাঁকা শাঁকে শব্দের বিভক্ত হওয়ার অনুরোধ করবে।
কুসালানন্দ

-2

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

perl -pi -e ""s/$val1/$val2/g"" file

ভেরিয়েবলগুলি বিবেচনা করুন যার মানগুলিতে শূন্যস্থান থাকতে পারে। পার্ল এক্সপ্রেশন ( "") এর চারপাশে খালি স্ট্রিংগুলি কিছুই করবে না।
কুসালানন্দ

-2

স্ট্রিং বিরতি

খারাপ => লিনাক্স একটি স্ট্রিং দেখুন $ old_run:

sed 's/$old_run/$new_run/'

শুভ => লিনাক্স একটি পরিবর্তনশীল $ old_run দেখুন:

sed 's/'$old_run'/'$new_run'/'

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