أرغب في تشغيل بحث واستبدال ملف HTML من خلال سطر الأوامر.
تبدو أمري مثل هذا:
sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html > index.html
عندما أقوم بتشغيل هذا وإلقاء نظرة على الملف بعد ذلك ، فإنه فارغ. حذف محتويات ملفي.
عندما أقوم بتشغيل هذا بعد استعادة الملف مرة أخرى:
sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
stdout
هي محتويات الملف ، وتم تنفيذ عملية البحث والاستبدال.
لماذا يحدث هذا؟
عندما يقوم Shell يرى > index.html
في سطر الأوامر ، فإنه يفتح الملف index.html
لـ كتابة ، محو جميع محتوياته السابقة.
لإصلاح هذا الأمر ، يتعين عليك تمرير الخيار -i
إلى sed
لإجراء التغييرات في السطر وإنشاء نسخة احتياطية من الملف الأصلي قبل إجراء التغييرات في مكانها:
sed -i.bak s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
بدون .bak ، سيفشل الأمر في بعض الأنظمة الأساسية ، مثل Mac OSX.
بديل ، مفيد ، هو نمط:
sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html
هذا له نفس التأثير إلى حد كبير ، دون استخدام الخيار -i
، ويعني بالإضافة إلى ذلك أنه إذا فشل البرنامج النصي sed لسبب ما ، فإن ملف الإدخال لا يتم تجميعه. علاوة على ذلك ، إذا كان التعديل ناجحًا ، فلن يتبقى ملف نسخ احتياطي. يمكن أن يكون هذا النوع من المصطلحات مفيدًا في Makefiles.
يحتوي الكثير من المخدرات على خيار -i
، ولكن ليس جميعهم ؛ و sedix هو واحد الذي لا. إذا كنت تهدف إلى قابلية النقل ، فمن الأفضل تجنبه.
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' index.html
يقوم هذا باستبدال عام في مكان على ملف index.html. نقلاً عن السلسلة يمنع مشاكل المسافة البيضاء في الاستعلام والاستبدال.
استخدم خيار sed's -i ، على سبيل المثال.
sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html
لتغيير ملفات متعددة (وحفظ نسخة احتياطية لكل منها كـ * .bak):
Perl -p -i -e "s/\|/x/g" *
سيأخذ جميع الملفات في الدليل ويستبدل |
بـ x
وهذا ما يسمى بـ "Perl pie" (سهل مثل دائري)
يجب أن تحاول استخدام الخيار -i
للتحرير الموضعي.
sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html
إذا كان لديك رابط لإضافته ، فجرب هذا. ابحث عن عنوان URL كما هو مذكور أعلاه (بدءًا من https ثم ينتهي بـ.com هنا) واستبدله بسلسلة URL. لقد استخدمت متغير $pub_url
هنا. s
هنا تعني البحث و g
تعني الاستبدال الشامل.
إنها تعمل !
تحذير: هذه طريقة خطيرة! يسيء إلى المخازن المؤقتة للإدخال/الإخراج في نظام التشغيل Linux ومع وجود خيارات محددة للتخزين المؤقت ، يمكنه العمل على الملفات الصغيرة. إنه فضول مثير للاهتمام. لكن لا تستخدمه في موقف حقيقي!
إلى جانب خيار -i
الخاص بـ sed
، يمكنك استخدام tee
الأداة المساعدة.
من man
:
كوم - قراءة من المدخلات القياسية والكتابة إلى الإخراج والملفات القياسية
لذلك ، سيكون الحل:
sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee | tee index.html
- هنا يتم تكرار tee
للتأكد من تخزين خط الأنابيب. ثم يتم حظر جميع الأوامر في خط الأنابيب حتى يحصلوا على بعض المدخلات للعمل عليها. يبدأ كل أمر في خط الأنابيب عندما تكون أوامر upstream قد كتبت مخزن مؤقت واحد للبايت (يتم تعريف الحجم في مكان ما ) لإدخال الأمر. لذا فإن الأمر الأخير tee index.html
، الذي يفتح الملف للكتابة وبالتالي يفرغ منه ، يعمل بعد انتهاء خط أنابيب المنبع والإخراج في المخزن المؤقت داخل خط الأنابيب.
على الأرجح لن يعمل ما يلي:
sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee index.html
- سيتم تشغيل كلا الأمرين لخط الأنابيب في نفس الوقت دون أي حظر. (بدون حظر ، يجب أن يمر خط الأنابيب بخط البايت سطراً بدلاً من المخزن المؤقت بواسطة المخزن المؤقت. كما هو الحال عند تشغيل cat | sed s/bar/GGG/
. دون حظر ، يكون أكثر تفاعلية وعادة ما يتم تشغيل خطوط الأنابيب من أمرين فقط دون تخزين مؤقت وحجب. يتم تخزين خطوط الأنابيب الأطول.) tee index.html
سيفتح الملف للكتابة وسيتم إفراغه. ومع ذلك ، إذا قمت بتشغيل التخزين المؤقت دائمًا ، فستعمل النسخة الثانية أيضًا.
المشكلة مع الأمر
sed 'code' file > file
هو أن file
يتم اقتطاعها من قِبل Shell قبل أن يتمكن sed من معالجتها بالفعل. نتيجة لذلك ، تحصل على ملف فارغ.
طريقة sed للقيام بذلك هي استخدام -i
للتعديل في المكان ، كما اقترحت الإجابات الأخرى. ومع ذلك ، هذا ليس دائما ما تريد. سيقوم -i
بإنشاء ملف مؤقت سيتم استخدامه بعد ذلك لاستبدال الملف الأصلي. هذا مشكلة إذا كان الملف الأصلي رابطًا (سيتم استبدال الرابط بملف عادي). إذا كنت بحاجة إلى الحفاظ على الروابط ، يمكنك استخدام متغير مؤقت لتخزين إخراج sed قبل إعادة كتابته مرة أخرى إلى الملف ، مثل هذا:
tmp=$(sed 'code' file); echo -n "$tmp" > file
الأفضل من ذلك ، استخدم printf
بدلاً من echo
لأن echo
من المحتمل أن تعالج \\
كـ \
في بعض الأصداف (على سبيل المثال ، الشرطة):
tmp=$(sed 'code' file); printf "%s" "$tmp" > file
والإجابة ed
:
printf "%s\n" '1,$s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' w q | ed index.html
لتكرار ما أجابه codaddict ، تعالج Shell إعادة التوجيه أولاً ، محو ملف "input.html" ، و {ثم تستدعي Shell أمر "sed" المار انها ملف فارغ الآن.
يمكنك استخدام Vim في وضع Ex:
ex -sc '%s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g|x' index.html
%
حدد جميع الخطوط
x
حفظ وإغلاق
كنت أبحث عن الخيار حيث يمكنني تحديد نطاق السطر والعثور على الإجابة. على سبيل المثال ، أريد تغيير Host1 إلى Host2 من السطر 36-57.
sed '36,57 s/Host1/Host2/g' myfile.txt > myfile1.txt
يمكنك استخدام خيار gi أيضًا لتجاهل حالة الأحرف.
sed '30,40 s/version/story/gi' myfile.txt > myfile1.txt
مع كل الاحترام الواجب للإجابات الصحيحة المذكورة أعلاه ، من الأفضل دائمًا "نصوص التشغيل الجاف" من هذا القبيل ، بحيث لا تفسد ملفك ويجب أن تبدأ من جديد من البداية.
ما عليك سوى الحصول على البرنامج النصي لإخراج الإخراج إلى سطر الأوامر بدلاً من كتابته إلى الملف ، على سبيل المثال ، مثل:
sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
OR
less index.html | sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g
وبهذه الطريقة يمكنك رؤية والتحقق من إخراج الأمر دون الحصول على الملف الخاص بك مبتوراً.