আমি সেড -i (ইনস-প্লেস এডিটিং) দিয়ে বহনযোগ্যতা কীভাবে অর্জন করতে পারি?


41

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

আমার ওয়েবসাইটের অংশটি জেনারেটেড স্ট্যাটিক এইচটিএমএল ফাইলগুলি ব্যবহার করে এবং এই সেড লাইনটি প্রতিটি পুনর্জন্মের পরে সঠিক ডক্টইপিইটি প্রবেশ করায়:

sed -i '1s/^/<!DOCTYPE html> \n/' ${file_name.html}

এটি sedলিনাক্সে জিএনইউ নিয়ে কাজ করে, তবে ফ্রিবিএসডি ব্যাকআপ কপির জন্য এক্সটেনশন sedহওয়ার -iবিকল্পের পরে প্রথম যুক্তিটি প্রত্যাশা করে । এটি দেখতে কেমন লাগে:

sed -i '' '1s/^/<!DOCTYPE html> \n/' ${file_name.html}

যাইহোক, GNU sedপ্রত্যাবর্তন করার সাথে সাথেই এই অভিব্যক্তিটি অনুসরণ করবে -i। (এটিতে নিউলাইন হ্যান্ডলিংয়ের সাথে সংশোধন করা দরকার তবে ইতিমধ্যে এখানে উত্তর দেওয়া হয়েছে )

অবশ্যই আমি স্ক্রিপ্টটির আমার সার্ভার অনুলিপিতে এই পরিবর্তনটি অন্তর্ভুক্ত করতে পারি, তবে এটি ভার্চুয়ানের জন্য আমার ভিসিএসের ব্যবহারকে গোলমাল করবে। একটি সম্পূর্ণ পোর্টেবল উপায়ে সেড দিয়ে এটি অর্জন করার কোনও উপায় আছে?


আপনার দেওয়া দুটি সেড স্নিপেটগুলি অভিন্ন, আপনি কি নিশ্চিত যে কোনও টাইপো নেই? এছাড়াও, আমি ঠিক ঠিক পরে ব্যাকআপ এক্সটেনশন সরবরাহ করে জিএনইউ -i
সিড

দুহ, এটি সন্ধানের জন্য ধন্যবাদ। আমি আমার প্রশ্ন স্থির করেছি। আমার সিডে ত্রুটির ফলে দ্বিতীয় পংক্তির ফলাফল, এটি '1s / ^ / <! DOCTYPE html> \ n /' ফাইল হিসাবে প্রত্যাশা করে এবং এটি এটি খুঁজে পায় না বলে অভিযোগ করে can't
লাল

উত্তর:


40

GNU সেড পরে একটি extensionচ্ছিক এক্সটেনশন গ্রহণ করে -i। হস্তক্ষেপের স্থান ছাড়াই এক্সটেনশনটি একই যুক্তিতে থাকতে হবে। এই বাক্য গঠনটি বিএসডি সেডেও কাজ করে।

sed -i.bak -e '…' SOMEFILE

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

আপনি যদি ব্যাকআপ ফাইলগুলি ব্যবহার করতে না চান, তবে শেডের কোন সংস্করণ উপলব্ধ তা পরীক্ষা করতে পারেন।

case $(sed --help 2>&1) in
  *GNU*) set sed -i;;
  *) set sed -i '';;
esac
"$@" -e '…' "$file"

বা বিকল্পভাবে, অবস্থানগত পরামিতি ক্লোবারিং এড়ানোর জন্য, একটি ফাংশন সংজ্ঞায়িত করুন।

case $(sed --help 2>&1) in
  *GNU*) sed_i () { sed -i "$@"; };;
  *) sed_i () { sed -i '' "$@"; };;
esac
sed_i -e '…' "$file"

আপনি বিরক্ত করতে না চাইলে পার্ল ব্যবহার করুন।

perl -i -pe '…' "$file"

আপনি যদি কোনও পোর্টেবল স্ক্রিপ্ট লিখতে চান তবে ব্যবহার করবেন না -i- এটি পসিক্সে নেই। হুডের নীচে শেড কী করে তা ম্যানুয়ালি করুন - এটি কোডের আরও একটি লাইন।

sed -e '…' "$file" >"$file.new"
mv -- "$file.new" "$file"

2
জিএনইউও sed -iবোঝায় -s। এবং জিএনইউ যাচাই করার সহজ উপায় sedহ'ল sed vকমান্ডটি যা জিএনইউর জন্য বৈধ নূপ তবে অন্য কোথাও ব্যর্থ।
মাইকজার্ভ

উপরের টিপস দ্বারা অনুপ্রাণিত হয়ে, যারা সত্যিই একটি চান তাদের জন্য এখানে একটি একক লাইন (কুরুচিপূর্ণ) পোর্টেবল সংস্করণ রয়েছে: যদিও এটি sed -i$(sed v < /dev/null 2> /dev/null || echo -n " ''") -e '...' "$file"জিএনইউ সিড না হয় তবে এটি একটি স্থান সন্নিবেশ করে -iযার পরে দুটি সিজে কোট দেওয়া হয় যাতে এটি ঘটে বিএসডিতে কাজ করে। জিএনইউ সেড পায় কেবল -i
ইভান এক্স

2
@ ইভানএক্স আমি জিএনইউ সেডের vপরীক্ষা করার জন্য কমান্ডের উপস্থিতিটি ব্যবহার করার বিষয়ে সতর্ক । ফ্রিবিএসডি যদি এটি বাস্তবায়নের সিদ্ধান্ত নেয়?
গিলস

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

1
@lapo বিকল্প একটি ফাংশন সংজ্ঞায়িত করা হয়, আমার সম্পাদনা দেখুন।
গিলস 'অসন্তুষ্ট হওয়া বন্ধ করুন'

10

sedখেলাকে সুন্দর করার কৌশল যদি আপনি না পান তবে আপনি চেষ্টা করতে পারেন:

  1. ব্যবহার করবেন না -i:

    sed '1s/^/<!DOCTYPE html> \n/' "${file_name.html}" > "${file_name.html}.tmp" &&
      mv "${file_name.html}.tmp" "${file_name.html}"
  2. পার্ল ব্যবহার করুন

    perl -i -pe 'print "<!DOCTYPE html> \n" if $.==1;' "${file_name.html}"

8

ইডি

আপনি সর্বদা edএকটি বিদ্যমান ফাইলে একটি লাইন প্রিপেন্ড করতে ব্যবহার করতে পারেন ।

$ printf '0a\n<!DOCTYPE html>\n.\nw\n' | ed my.html

বিস্তারিত

চারপাশের বিটগুলি ফাইলটিকে সেই লাইন যুক্ত <!DOCTYPE html>করার edনির্দেশ দেওয়ার নির্দেশ দেয় my.html

sed

আমি বিশ্বাস করি যে এই আদেশটি sedব্যবহার করা যেতে পারে:

$ sed -i '1i<!DOCTYPE html>\n` testfile.csv

আমি শেষ পর্যন্ত পার্লের কাছে অবলম্বন করেছি, তবে এড ব্যবহার করা একটি ভাল বিকল্প যা ইউনিক্সের মতো ব্যবহারকারীদের মধ্যে যেমন জনপ্রিয় হওয়া উচিত তেমন জনপ্রিয় নয়।
রেড

@ রেড - আপনি ইস্যু সমাধান করেছেন শুনে খুশী। হ্যাঁ, আমি এটি আগে কখনও দেখিনি, গুগলিং এটি চালু করেছিল এবং এটি এটি করার পক্ষে সবচেয়ে পোর্টেবল, উপযুক্ত উপায় বলে মনে হয়েছিল।
slm

7

perl -iহুডের নীচে যা হয় তা আপনি নিজেও করতে পারেন :

{ rm -f file && { echo '<!DOCTYPE html>'; cat; } > file;} < file

যেমন perl -i, কোনও ব্যাকআপ নেই, এবং এখানে দেওয়া বেশিরভাগ সমাধানের মতো, সাবধান থাকুন এটি ফাইলের অনুমতি, মালিকানা প্রভাবিত করতে পারে এবং একটি সিমলিংককে একটি নিয়মিত ফাইলে পরিণত করতে পারে।

সঙ্গে:

sed '1i\
<!DOCTYPE html>' file 1<> file

sedফাইলটি নিজেই ওভাররাইট করে দেবে, সুতরাং এটি মালিকানা এবং অনুমতি বা সিমলিংকে প্রভাবিত করবে না। এটি জিএনইউতে কাজ করে sedকারণ কমান্ড দিয়ে ওভাররাইট করার আগে sedসাধারণত file(আমার ক্ষেত্রে 4 কে) থেকে পূর্ণ ডেটা পূর্ণ বাফারটি পড়বে i। ফাইলটি 4k এর বেশি হলে sedতার আউটপুটটিও বাফার করে work

মূলত sedপড়া এবং লেখার জন্য 4 কে ব্লকে কাজ করে। যদি সন্নিবেশ করার লাইনটি 4k এর চেয়ে ছোট হয় sedতবে এটি এখনও পড়েনি এমন কোনও ব্লক কখনই ওভাররাইট করতে পারে না।

যদিও আমি এটিতে বিশ্বাস করি না।


echo '<!DOCTYPE html>'"" উদ্ধৃতি না দিয়ে থাকা বা পালানো উচিত ।
খ্রি

@ অ্যাড ভাল পয়েন্ট। আমি সেই বাগটি ভুলে যেতে চাইছি inte ইন্টারেক্টিভ ব্যাশ / জেডএসএফের বৈশিষ্ট্য আমি সাধারণত নিজের জন্য এটি অক্ষম করে থাকি।
স্টাফেন চেজেলাস

এটি এখানে খুব কম উত্তরগুলির মধ্যে একটি যা ইতিমধ্যে বিদ্যমান কিনা তা পরীক্ষা করেই কোনও স্থির, অনুমানযোগ্য নাম সহ কোনও "টেম্প ফাইল" এ পুনর্নির্দেশের প্রশস্ত উন্মুক্ত সুরক্ষা গর্ত নেই। আমি বিশ্বাস করি এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। গ্রুপ কমান্ড ব্যবহারের খুব সুন্দর প্রদর্শন।
ওয়াইল্ডকার্ড

3

ফ্রিবিএসডি সেড , যা ম্যাক ওএস এক্সেও ব্যবহৃত হয়, নিম্নলিখিত (রেজেক্স) কমান্ডটি সঠিকভাবে এবং দ্ব্যর্থহীনভাবে সংজ্ঞা ও স্বীকৃতি -eদেওয়ার জন্য -iসুইচের পরে বিকল্পের প্রয়োজন ।

অন্য কথায়, sed -i -e ...ফ্রিবিএসডি এবং জিএনইউ উভয়ের সাথে কাজ করা উচিত sed

আরও সাধারণভাবে, ফ্রিবিএসডি- sed -iর পরে ব্যাকআপ এক্সটেনশন বাদ দেওয়ার জন্য কিছু স্পষ্ট sedবিকল্পের প্রয়োজন হয় বা এর কমান্ড-লাইন আর্গুমেন্টগুলি বিশ্লেষণ করার সময় -iফ্রিবিএসডি-র পক্ষ থেকে বিভ্রান্তি এড়াতে নিম্নলিখিতগুলি অনুসরণ করে স্যুইচ করুন sed

(দ্রষ্টব্য, তবে, যে sedস্থানের ফাইল সম্পাদনাগুলি ফাইল ইনোড পরিবর্তনের দিকে পরিচালিত করে, ফাইলগুলির "ইন-প্লেস" সম্পাদনা দেখুন )।

(ক সাধারণ ইঙ্গিতটি হিসেবে FreeBSD 'র সাম্প্রতিক সংস্করণে sedআছে -rসুইচ গনুহ সাথে সামঞ্জস্যের বৃদ্ধি sed)।

echo a > testfile.txt
ls -li testfile.txt
#gsed -i -e 's/a/A/' testfile.txt
#bsdsed -i 's/a/A/' testfile.txt  # does not work
bsdsed -i -e 's/a/A/' testfile.txt
ls -li testfile.txt
cat testfile.txt

5
না, bsdsed -i -e 's/a/A/'হয় না এই স্থানে সম্পাদনা, তবে তা "-e" প্রত্যয় মূল সংরক্ষণ সাথে একসঙ্গে সম্পাদন এর ( testfile.txt-e)।
স্টাফেন চেজেলাস 22'15

নোট করুন যে জিএনইউ সেডও ফ্রিবিএসডি এর সাথে সামঞ্জস্যের জন্য -E (-r এর সাথে) সমর্থন করে। -আমার পরবর্তী পসিক্স সংস্করণে নির্দিষ্ট করা হতে পারে, সুতরাং আমাদের সকলকে সেই অজ্ঞান সম্পর্কে ভুলে যাওয়া উচিত এবং এটির অস্তিত্ব কখনও নেই tend
স্টাফেন চেজেলাস

2

sed -iযতটা সম্ভব জাতির শর্ত এড়ানো চলাকালীন পোর্টেবলভাবে একটি একক ফাইলের জন্য অনুকরণ করতে :

sed 'script' <<FILE >file
$(cat file)
FILE

যাইহোক, এটি সেই সম্ভাব্য সমস্যাটিও পরিচালনা করে sed -iযা ডিরেক্টরি এবং ফাইল অনুমতিগুলির উপর নির্ভর করে এটিতে পরিচয় করিয়ে দেয় sed -iকোনও ব্যবহারকারীকে এমন কোনও ফাইলকে ওভাররাইট করতে সক্ষম করতে পারে যা সেই ব্যবহারকারীর সম্পাদনার অনুমতি নেই।

আপনি ব্যাকআপগুলিও এর মতো করতে পারেন:

sed 'script' <<FILE >file
$(tee file.old <file)
FILE

2

আপনি প্রাক্তন মোডে ভিম ব্যবহার করতে পারেন:

ex -sc '1i|<!DOCTYPE html>' -cx file
  1. 1 প্রথম লাইন নির্বাচন করুন

  2. i পাঠ্য এবং নিউলাইন .োকান

  3. x সংরক্ষণ করেন এবং বন্ধ করেন

বা এমনকি মতামত হিসাবে, সাধারণ পুরানো স্ট্যান্ডার্ড ex :

printf '%s\n' 1i '<!DOCTYPE html>' . x | ex file 

এখানে ভিম-নির্দিষ্ট কিছু নেই। এটি সম্পূর্ণরূপে POSIX স্পেসিফিকেশনগুলিরex সাথে মেনে চলে , একাধিক পতাকা সমর্থন করার জন্য বাস্তবায়নের প্রয়োজন হয় না -c। সুনির্দিষ্ট বহনযোগ্যতার জন্য আমি ব্যবহার করবprintf '%s\n' 1i '<!DOCTYPE html>' . x | ex file
ওয়াইল্ডকার্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.