কোনও ফাইলের মধ্যে একটি লাইন যুক্ত করা কেবল যদি এটি ইতিমধ্যে বিদ্যমান না থাকে


157

কনফিগার ফাইলের শেষে আমাকে নিম্নলিখিত লাইনটি যুক্ত করতে হবে:

include "/configs/projectname.conf"

বলা একটি ফাইল lighttpd.conf

আমি এটি sedকরার জন্য ব্যবহারের দিকে তাকাচ্ছি , তবে কীভাবে তা কার্যকর করতে পারি না।

লাইনটি ইতিমধ্যে বিদ্যমান না থাকলে আমি কীভাবে এটি সন্নিবেশ করব?


আপনি যদি কোনও crudiniইনআই -ফাইল সম্পাদনা করার চেষ্টা করছেন তবে সরঞ্জামটি একটি ভাল বিকল্প হতে পারে (তবে এখনও লাইটথটিপিডির জন্য নয়)
রুও 7777

উত্তর:


291

শুধু সহজ রাখুন :)

গ্রেপ + প্রতিধ্বনি যথেষ্ট হওয়া উচিত:

grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar
  • -q শান্ত হও
  • -x পুরো লাইন মেলে
  • -F প্যাটার্ন একটি সরল স্ট্রিং
  • https://linux.die.net/man/1/grep

সম্পাদনা করুন: @ সিসারিন এবং @ থিজ-ওয়াটারস পরামর্শগুলি অন্তর্ভুক্ত


2
আউটপুট দমন করতে আমি গ্রেপ্তারে -Q স্যুইচটি যুক্ত করব: grep -vq ...
ডেভ কির্বি

1
FYI, -v এবং&& ব্যবহার করে কৌতুকটি করতে দেখায় না, যদিও || -v কাজ ছাড়া।
বিপিজিজি

3
এটি কেবল খুব সাধারণ লাইনের জন্য কাজ করে। অন্যথায়, গ্রেপ আপনার লাইনের বেশিরভাগ অ-আলফা অক্ষরকে নিদর্শন হিসাবে ব্যাখ্যা করে, যার ফলে এটি ফাইলের লাইনটি সনাক্ত না করে।
সেরিন

2
সুন্দর সমাধান। এটি অবশ্যই আরও জটিল অভিব্যক্তি ট্রিগার করার জন্য কাজ করে। মাইনটি একটি কনফিগার ফাইলে বহুবিধ হের্ডোকের echoট্রিগার করতে ব্যবহার করে cat
এরিক এল

2
-sফাইলটি উপস্থিত না থাকলে ত্রুটি উপেক্ষা করার জন্য যুক্ত করুন , ঠিক সেই লাইন দিয়ে একটি নতুন ফাইল তৈরি করুন।
ফ্রাঙ্ক

78

এটি একটি পরিষ্কার, পঠনযোগ্য এবং পুনরায় ব্যবহারযোগ্য সমাধান হবে এটি ব্যবহার করে grepএবং echoযদি কোনও ফাইলের মধ্যে ইতিমধ্যে উপস্থিত না থাকে তবে কেবল একটি লাইন যুক্ত করা:

LINE='include "/configs/projectname.conf"'
FILE='lighttpd.conf'
grep -qF -- "$LINE" "$FILE" || echo "$LINE" >> "$FILE"

আপনার প্রয়োজন হলে পুরো লাইনটি ব্যবহার করুন grep -xqF

-sফাইলটি উপস্থিত না থাকলে ত্রুটি উপেক্ষা করার জন্য যুক্ত করুন , ঠিক সেই লাইন দিয়ে একটি নতুন ফাইল তৈরি করুন।


5
: এটা একটি ফাইল যেখানে আপনি রুটের অনুমতি প্রয়োজন যদিsudo grep -qF "$LINE" "$FILE" || echo "$LINE" | sudo tee -a "$FILE"
nebffa

এটি যখন লাইনের সাথে শুরু হয় তখন আসলে কাজ করে না -
হাইপারকনট

@ জেসেরো: ভালো কথা! আমি --গ্রেপ কমান্ডে যুক্ত করেছি, সুতরাং এটি কোনও বিকল্প হিসাবে ড্যাশ দিয়ে শুরু করা কোনও $ লাইনকে ব্যাখ্যা করবে না।
rubo77

13

এখানে একটি sedসংস্করণ:

sed -e '\|include "/configs/projectname.conf"|h; ${x;s/incl//;{g;t};a\' -e 'include "/configs/projectname.conf"' -e '}' file

যদি আপনার স্ট্রিং পরিবর্তনশীল হয়:

string='include "/configs/projectname.conf"'
sed -e "\|$string|h; \${x;s|$string||;{g;t};a\\" -e "$string" -e "}" file

একটি কমান্ডের জন্য যা সম্পূর্ণ / আপডেট হওয়া কনফিগার ফাইল এন্ট্রি সহ আংশিক স্ট্রিংকে প্রতিস্থাপন করে বা প্রয়োজনীয় হিসাবে লাইনটি sed -i -e '\|session.*pam_mkhomedir.so|h; ${x;s/mkhomedir//;{g;tF};a\' -e 'session\trequired\tpam_mkhomedir.so umask=0022' -e '};:F;s/.*mkhomedir.*/session\trequired\tpam_mkhomedir.so umask=0022/g;' /etc/pam.d/common-session
সংযোজন করে

ভাল লাগল, এটি আমাকে অনেক +1 সাহায্য করেছে। আপনি দয়া করে, আপনার অভ্যাসটি ব্যাখ্যা করতে পারেন?
রাহুল

আমি এই সমাধানটির একটি এনোটোটেড ব্যাখ্যা দেখতে চাই। আমি sedকয়েক বছর ধরে ব্যবহার করেছি তবে বেশিরভাগই কেবল sকমান্ড। holdএবং patternস্থান অদলবদল আমাকে বহির্ভূত।
উত্তরঃ

11

যদি কোনও সুরক্ষিত ফাইলে লিখিত হয় তবে @drAlberT এবং @ রুব 77 s এর উত্তরগুলি আপনার পক্ষে কাজ করতে পারে না কারণ কেউ সুডো করতে পারে না >>তেমনি একটি সহজ সমাধানtee --append হ'ল ব্যবহার করা (বা, ম্যাকোএসে tee -a):

LINE='include "/configs/projectname.conf"'
FILE=lighttpd.conf
grep -qF "$LINE" "$FILE"  || echo "$LINE" | sudo tee --append "$FILE"

6

যদি একদিন, অন্য কেউ আছে "লিগ্যাসি কোড" হিসাবে এই কোড দিয়ে মোকাবেলা করতে, তাহলে সেই ব্যক্তি কৃতজ্ঞ যদি আপনি যেমন একটি কম সহজবোধ্য কোড লিখতে হবে

grep -q -F 'include "/configs/projectname.conf"' lighttpd.conf
if [ $? -ne 0 ]; then
  echo 'include "/configs/projectname.conf"' >> lighttpd.conf
fi

1
দুঃখিত, যদি আপনি শেল না জানেন, তবে যান এবং উইন্ডোজ পরিচালনা করুন। && এবং || ব্যবহার করে সমাধানগুলি সাধারণ শেল সিনট্যাক্স, এবং কোনও সক্ষম প্রশাসক দ্বারা বোঝা উচিত। মোটেও তেমন কিছুই রহস্যজনক কিছু নেই।
গ্রাহাম নিকোলস

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


6

অন্য একটি সমাধান সমাধান হ'ল সর্বদা সর্বশেষ লাইনে যুক্ত করুন এবং একটি বিদ্যমান বিদ্যমান মুছুন।

sed -e '$a\' -e '<your-entry>' -e "/<your-entry-properly-escaped>/d"

"যথাযথভাবে পালিয়ে যাওয়া" এর অর্থ আপনার প্রবেশের সাথে মিলে যাওয়া একটি রেজেক্স স্থাপন করা, অর্থাৎ আপনার প্রকৃত প্রবেশ থেকে সমস্ত রেজেক্স নিয়ন্ত্রণ থেকে মুক্তি পাওয়া, অর্থাৎ ^ $ / *? + () এর সামনে একটি ব্যাকস্ল্যাশ রাখা।

এটি আপনার ফাইলের শেষ লাইনে ব্যর্থ হতে পারে বা যদি কোনও জটলা নিউলাইন না থাকে তবে আমি নিশ্চিত নই, তবে কিছু নিফটি শাখা দ্বারা এটি মোকাবেলা করা যেতে পারে ...


1
সুন্দর ওয়ান-লাইনার, সংক্ষিপ্ত এবং পড়া সহজ। ইত্যাদি / হোস্টগুলি আপডেট করার জন্য দুর্দান্ত কাজ করে:sed -i.bak -e '$a\' -e "$NEW_IP\t\t$HOST.domain\t$HOST" -e "/.*$HOST/d" /etc/hosts
নোয়াম মানস

একটি ছোট সংস্করণ:sed -i -e '/<entry>/d; $a <entry>'
জেরুমে পাউিলার

@ জিজ আমি মনে করি এটি ইতিমধ্যে ফাইলের শেষে এন্ট্রি থাকলে ব্যর্থ হবে, কারণ dকমান্ডটি aসেড প্রোগ্রামটি পুনরায় চালু করবে এবং এরপরে পেপেন্ডটি এড়িয়ে যাবে, যদি মুছুনটি শেষ লাইনে থাকে।
রবিন 479

@ Robin479 জঘন্য, append আগে মৃত্যুদন্ড কার্যকর করতে হবে delete: sed -i -e '$a<entry>' -e '/<entry>/d'। এটি আপনার মূল উত্তরের চেয়ে প্রায় একই same
জারুম পাইউলার

3

awk ব্যবহার করুন

awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file file

এটি কি 'ফাইল ফাইল' বা 'ফাইল'?
ওয়েবদেবগুই

এটা file fileকরা হয়েছে কারণ এটি একই ফাইল দুই পাস করে তোলে। NR==FNRপ্রথম পাসে সত্য, তবে দ্বিতীয়টি নয়। এটি একটি সাধারণ আওক বুদ্ধিমান।
ট্রিপলি

1

গ্রেপ ব্যবহার করে দেওয়া উত্তরগুলি ভুল। পুরো লাইনটি মেলে ধরতে আপনাকে একটি -x বিকল্প যুক্ত করতে #text to addহবে অন্যথায় ঠিক যোগ করার দিকে তাকানোর মতো লাইনের লাইনগুলি এখনও মিলবে text to add

সুতরাং সঠিক সমাধানটি হ'ল কিছু:

grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar

1

সেড ব্যবহার: এটি লাইনের শেষে প্রবেশ করবে। আপনি অবশ্যই যথারীতি চলকগুলিতে পাস করতে পারেন।

grep -qxF "port=9033" $light.conf
if [ $? -ne 0 ]; then
  sed -i "$ a port=9033" $light.conf
else
    echo "port=9033 already added"
fi

Oneliner সেড ব্যবহার

grep -qxF "port=9033" $lightconf || sed -i "$ a port=9033" $lightconf

প্রতিধ্বনি ব্যবহার করা মূলের নীচে কাজ নাও করতে পারে তবে এটি এর মতো কাজ করবে। তবে এটি আপনাকে পাসওয়ার্ডের জন্য জিজ্ঞাসা করতে পারে বলে আপনি যদি এটি করার চেষ্টা করছেন তবে আপনাকে জিনিসগুলি স্বয়ংক্রিয় করতে দেয় না।

আমি যখন কোনও নির্দিষ্ট ব্যবহারকারীর জন্য মূল থেকে সম্পাদনা করার চেষ্টা করছিলাম তখন আমার একটি সমস্যা হয়েছিল। শুধু $usernameআগে যোগ করা আমার জন্য একটি স্থির ছিল।

grep -qxF "port=9033" light.conf
if [ $? -ne 0 ]; then
  sudo -u $user_name echo "port=9033" >> light.conf
else
    echo "already there"    
fi

স্ট্যাকওভারফ্লোতে স্বাগতম! উত্তর পোস্ট করার আগে দয়া করে প্রশ্নটি মনোযোগ সহকারে পড়ুন - ওপি জিজ্ঞাসা করেছিল যে
সেড

-1

আমার প্রয়োজন সীমিত লেখার অনুমতি সহ একটি ফাইল সম্পাদনা করা sudo। ঘোস্টডোগ 74 এর উত্তর থেকে কাজ করা এবং একটি টেম্প ফাইল ব্যবহার করে:

awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file > /tmp/file
sudo mv /tmp/file file

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